This commit was manufactured by cvs2svn to create branch 'release_19'.
llvm-svn: 87297
diff --git a/safecode/CVSROOT/checkoutlist b/safecode/CVSROOT/checkoutlist
new file mode 100755
index 0000000..b04b350
--- /dev/null
+++ b/safecode/CVSROOT/checkoutlist
@@ -0,0 +1,13 @@
+# The "checkoutlist" file is used to support additional version controlled
+# administrative files in $CVSROOT/CVSROOT, such as template files.
+#
+# The first entry on a line is a filename which will be checked out from
+# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
+# The remainder of the line is an error message to use if the file cannot
+# be checked out.
+#
+# File format:
+#
+# [<whitespace>]<filename><whitespace><error message><end-of-line>
+#
+# comment lines begin with '#'
diff --git a/safecode/CVSROOT/commitinfo b/safecode/CVSROOT/commitinfo
new file mode 100755
index 0000000..b19e7b7
--- /dev/null
+++ b/safecode/CVSROOT/commitinfo
@@ -0,0 +1,15 @@
+# The "commitinfo" file is used to control pre-commit checks.
+# The filter on the right is invoked with the repository and a list
+# of files to check. A non-zero exit of the filter program will
+# cause the commit to be aborted.
+#
+# The first entry on a line is a regular expression which is tested
+# against the directory that the change is being committed to, relative
+# to the $CVSROOT. For the first match that is found, then the remainder
+# of the line is the name of the filter to run.
+#
+# If the repository name does not match any of the regular expressions in this
+# file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name "ALL" appears as a regular expression it is always used
+# in addition to the first matching regex or "DEFAULT".
diff --git a/safecode/CVSROOT/config b/safecode/CVSROOT/config
new file mode 100755
index 0000000..ff43ec0
--- /dev/null
+++ b/safecode/CVSROOT/config
@@ -0,0 +1,14 @@
+# Set this to "no" if pserver shouldn't check system users/passwords
+#SystemAuth=no
+
+# Put CVS lock files in this directory rather than directly in the repository.
+#LockDir=/var/lock/cvs
+
+# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top
+# level of the new working directory when using the `cvs checkout'
+# command.
+#TopLevelAdmin=no
+
+# Set `LogHistory' to `all' or `TOFEWGCMAR' to log all transactions to the
+# history file, or a subset as needed (ie `TMAR' logs all write operations)
+#LogHistory=TOFEWGCMAR
diff --git a/safecode/CVSROOT/cvswrappers b/safecode/CVSROOT/cvswrappers
new file mode 100755
index 0000000..0accaf1
--- /dev/null
+++ b/safecode/CVSROOT/cvswrappers
@@ -0,0 +1,23 @@
+# This file affects handling of files based on their names.
+#
+# The -t/-f options allow one to treat directories of files
+# as a single file, or to transform a file in other ways on
+# its way in and out of CVS.
+#
+# The -m option specifies whether CVS attempts to merge files.
+#
+# The -k option specifies keyword expansion (e.g. -kb for binary).
+#
+# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
+#
+# wildcard [option value][option value]...
+#
+# where option is one of
+# -f from cvs filter value: path to filter
+# -t to cvs filter value: path to filter
+# -m update methodology value: MERGE or COPY
+# -k expansion mode value: b, o, kkv, &c
+#
+# and value is a single-quote delimited value.
+# For example:
+#*.gif -k 'b'
diff --git a/safecode/CVSROOT/editinfo b/safecode/CVSROOT/editinfo
new file mode 100755
index 0000000..d78886c
--- /dev/null
+++ b/safecode/CVSROOT/editinfo
@@ -0,0 +1,21 @@
+# The "editinfo" file is used to allow verification of logging
+# information. It works best when a template (as specified in the
+# rcsinfo file) is provided for the logging procedure. Given a
+# template with locations for, a bug-id number, a list of people who
+# reviewed the code before it can be checked in, and an external
+# process to catalog the differences that were code reviewed, the
+# following test can be applied to the code:
+#
+# Making sure that the entered bug-id number is correct.
+# Validating that the code that was reviewed is indeed the code being
+# checked in (using the bug-id number or a seperate review
+# number to identify this particular code set.).
+#
+# If any of the above test failed, then the commit would be aborted.
+#
+# Actions such as mailing a copy of the report to each reviewer are
+# better handled by an entry in the loginfo file.
+#
+# One thing that should be noted is the the ALL keyword is not
+# supported. There can be only one entry that matches a given
+# repository.
diff --git a/safecode/CVSROOT/loginfo b/safecode/CVSROOT/loginfo
new file mode 100755
index 0000000..a4d5088
--- /dev/null
+++ b/safecode/CVSROOT/loginfo
@@ -0,0 +1,27 @@
+# The "loginfo" file controls where "cvs commit" log information
+# is sent. The first entry on a line is a regular expression which must match
+# the directory that the change is being made to, relative to the
+# $CVSROOT. If a match is found, then the remainder of the line is a filter
+# program that should expect log information on its standard input.
+#
+# If the repository name does not match any of the regular expressions in this
+# file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name ALL appears as a regular expression it is always used
+# in addition to the first matching regex or DEFAULT.
+#
+# You may specify a format string as part of the
+# filter. The string is composed of a `%' followed
+# by a single format character, or followed by a set of format
+# characters surrounded by `{' and `}' as separators. The format
+# characters are:
+#
+# s = file name
+# V = old version number (pre-checkin)
+# v = new version number (post-checkin)
+#
+# For example:
+#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
+# or
+#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog
+^safecode /home/vadve/shared/InternalCVS/CVSROOT/commit-diffs.pl %{sVv} criswell@cs.uiuc.edu
diff --git a/safecode/CVSROOT/modules b/safecode/CVSROOT/modules
new file mode 100755
index 0000000..cb9e9ef
--- /dev/null
+++ b/safecode/CVSROOT/modules
@@ -0,0 +1,26 @@
+# Three different line formats are valid:
+# key -a aliases...
+# key [options] directory
+# key [options] directory files...
+#
+# Where "options" are composed of:
+# -i prog Run "prog" on "cvs commit" from top-level of module.
+# -o prog Run "prog" on "cvs checkout" of module.
+# -e prog Run "prog" on "cvs export" of module.
+# -t prog Run "prog" on "cvs rtag" of module.
+# -u prog Run "prog" on "cvs update" of module.
+# -d dir Place module in directory "dir" instead of module name.
+# -l Top-level directory only -- do not recurse.
+#
+# NOTE: If you change any of the "Run" options above, you'll have to
+# release and re-checkout any working directories of these modules.
+#
+# And "directory" is a path to a directory relative to $CVSROOT.
+#
+# The "-a" option specifies an alias. An alias is interpreted as if
+# everything on the right of the "-a" had been typed on the command line.
+#
+# You can encode a module within a module by using the special '&'
+# character to interpose another module into the current module. This
+# can be useful for creating a module that consists of many directories
+# spread out over the entire source repository.
diff --git a/safecode/CVSROOT/notify b/safecode/CVSROOT/notify
new file mode 100755
index 0000000..34f0bc2
--- /dev/null
+++ b/safecode/CVSROOT/notify
@@ -0,0 +1,12 @@
+# The "notify" file controls where notifications from watches set by
+# "cvs watch add" or "cvs edit" are sent. The first entry on a line is
+# a regular expression which is tested against the directory that the
+# change is being made to, relative to the $CVSROOT. If it matches,
+# then the remainder of the line is a filter program that should contain
+# one occurrence of %s for the user to notify, and information on its
+# standard input.
+#
+# "ALL" or "DEFAULT" can be used in place of the regular expression.
+#
+# For example:
+#ALL mail %s -s "CVS notification"
diff --git a/safecode/CVSROOT/rcsinfo b/safecode/CVSROOT/rcsinfo
new file mode 100755
index 0000000..49e59f4
--- /dev/null
+++ b/safecode/CVSROOT/rcsinfo
@@ -0,0 +1,13 @@
+# The "rcsinfo" file is used to control templates with which the editor
+# is invoked on commit and import.
+#
+# The first entry on a line is a regular expression which is tested
+# against the directory that the change is being made to, relative to the
+# $CVSROOT. For the first match that is found, then the remainder of the
+# line is the name of the file that contains the template.
+#
+# If the repository name does not match any of the regular expressions in this
+# file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name "ALL" appears as a regular expression it is always used
+# in addition to the first matching regex or "DEFAULT".
diff --git a/safecode/CVSROOT/taginfo b/safecode/CVSROOT/taginfo
new file mode 100755
index 0000000..274a46d
--- /dev/null
+++ b/safecode/CVSROOT/taginfo
@@ -0,0 +1,20 @@
+# The "taginfo" file is used to control pre-tag checks.
+# The filter on the right is invoked with the following arguments:
+#
+# $1 -- tagname
+# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
+# $3 -- repository
+# $4-> file revision [file revision ...]
+#
+# A non-zero exit of the filter program will cause the tag to be aborted.
+#
+# The first entry on a line is a regular expression which is tested
+# against the directory that the change is being committed to, relative
+# to the $CVSROOT. For the first match that is found, then the remainder
+# of the line is the name of the filter to run.
+#
+# If the repository name does not match any of the regular expressions in this
+# file, the "DEFAULT" line is used, if it is specified.
+#
+# If the name "ALL" appears as a regular expression it is always used
+# in addition to the first matching regex or "DEFAULT".
diff --git a/safecode/CVSROOT/verifymsg b/safecode/CVSROOT/verifymsg
new file mode 100755
index 0000000..86f747c
--- /dev/null
+++ b/safecode/CVSROOT/verifymsg
@@ -0,0 +1,21 @@
+# The "verifymsg" file is used to allow verification of logging
+# information. It works best when a template (as specified in the
+# rcsinfo file) is provided for the logging procedure. Given a
+# template with locations for, a bug-id number, a list of people who
+# reviewed the code before it can be checked in, and an external
+# process to catalog the differences that were code reviewed, the
+# following test can be applied to the code:
+#
+# Making sure that the entered bug-id number is correct.
+# Validating that the code that was reviewed is indeed the code being
+# checked in (using the bug-id number or a seperate review
+# number to identify this particular code set.).
+#
+# If any of the above test failed, then the commit would be aborted.
+#
+# Actions such as mailing a copy of the report to each reviewer are
+# better handled by an entry in the loginfo file.
+#
+# One thing that should be noted is the the ALL keyword is not
+# supported. There can be only one entry that matches a given
+# repository.
diff --git a/safecode/Makefile b/safecode/Makefile
new file mode 100755
index 0000000..5b37eff
--- /dev/null
+++ b/safecode/Makefile
@@ -0,0 +1,19 @@
+#
+# This is a sample Makefile for a project that uses LLVM.
+#
+
+#
+# Indicates our relative path to the top of the project's root directory.
+#
+LEVEL = .
+
+#
+# Directories that needs to be built.
+#
+DIRS = lib runtime
+
+#
+# Include the Master Makefile that knows how to build all.
+#
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/Makefile.common.in b/safecode/Makefile.common.in
new file mode 100755
index 0000000..02237e6
--- /dev/null
+++ b/safecode/Makefile.common.in
@@ -0,0 +1,34 @@
+PROJECT_NAME := safecode
+PROJ_VERSION := 1.0
+
+# Set this variable to the top of the LLVM source tree.
+LLVM_SRC_ROOT = @LLVM_SRC@
+
+# Set this variable to the top level directory where LLVM was built
+# (this is *not* the same as OBJ_ROOT as defined in LLVM's Makefile.config).
+LLVM_OBJ_ROOT = @LLVM_OBJ@
+
+# Set the source root and source directory pathnames
+####PROJ_SRC_DIR := $(subst //,/,@abs_top_srcdir@/$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR)))
+
+PROJ_SRC_ROOT := $(subst //,/,@abs_top_srcdir@)
+
+# Set the root directory of this project's object files
+PROJ_OBJ_ROOT := $(subst //,/,@abs_top_objdir@)
+
+# Set the root directory of this project's install prefix
+PROJ_INSTALL_ROOT := @prefix@
+
+# Set the location of the pool allocation project
+POOLALLOC_SRCDIR := @poolallocsrcdir@
+POOLALLOC_OBJDIR := @poolallocobjdir@
+
+# Include LLVM's Master Makefile.
+include $(LLVM_SRC_ROOT)/Makefile.common
+
+# All of the code should additionally look inside the pool allocation source
+# code for include files
+CFLAGS += -DSAFECODE -I$(POOLALLOC_SRCDIR)/include -I$(POOLALLOC_OBJDIR)/include
+CXXFLAGS += -DSAFECODE -I$(POOLALLOC_SRCDIR)/include -I$(POOLALLOC_OBJDIR)/include
+CPPFLAGS += -DSAFECODE -I$(POOLALLOC_SRCDIR)/include -I$(POOLALLOC_OBJDIR)/include
+
diff --git a/safecode/Makefile.config b/safecode/Makefile.config
new file mode 100755
index 0000000..1649978
--- /dev/null
+++ b/safecode/Makefile.config
@@ -0,0 +1,16 @@
+#
+# Set this variable to the top of the LLVM source tree.
+#
+LLVM_SRC_ROOT = $(LEVEL)/../..
+
+#
+# Set this variable to the top level directory where LLVM was built
+# (i.e. where all of the object files are located).
+#
+#LLVM_OBJ_ROOT = $(LEVEL)/../..
+
+#
+# Include LLVM's Makefile Makefile.
+#
+include $(LLVM_SRC_ROOT)/Makefile.config
+
diff --git a/safecode/README b/safecode/README
new file mode 100755
index 0000000..2b2fa73
--- /dev/null
+++ b/safecode/README
@@ -0,0 +1 @@
+Need to change a few definitions in Makefile to use the Makefile
diff --git a/safecode/autoconf/AutoRegen.sh b/safecode/autoconf/AutoRegen.sh
new file mode 100755
index 0000000..af6c0a4
--- /dev/null
+++ b/safecode/autoconf/AutoRegen.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+die () {
+ echo "$@" 1>&2
+ exit 1
+}
+test -d autoconf && test -f autoconf/configure.ac && cd autoconf
+test -f configure.ac || die "Can't find 'autoconf' dir; please cd into it first"
+autoconf --version | egrep '2\.5[0-9]' > /dev/null
+if test $? -ne 0 ; then
+ die "Your autoconf was not detected as being 2.5x"
+fi
+cwd=`pwd`
+if test -d ../../../autoconf/m4 ; then
+ cd ../../../autoconf/m4
+ llvm_m4=`pwd`
+ cd $cwd
+elif test -d ../../llvm/autoconf/m4 ; then
+ cd ../../llvm/autoconf/m4
+ llvm_m4=`pwd`
+ cd $cwd
+else
+ die "Can't find the LLVM autoconf/m4 directory. The project should be checked out to projects directory"
+fi
+echo "Regenerating aclocal.m4 with aclocal"
+rm -f aclocal.m4
+aclocal -I $llvm_m4 -I "$llvm_m4/.." || die "aclocal failed"
+echo "Regenerating configure with autoconf 2.5x"
+autoconf --warnings=all -o ../configure configure.ac || die "autoconf failed"
+cd ..
+exit 0
diff --git a/safecode/autoconf/LICENSE.TXT b/safecode/autoconf/LICENSE.TXT
new file mode 100755
index 0000000..72fdd39
--- /dev/null
+++ b/safecode/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/safecode/autoconf/config.guess b/safecode/autoconf/config.guess
new file mode 100755
index 0000000..cc726cd
--- /dev/null
+++ b/safecode/autoconf/config.guess
@@ -0,0 +1,1388 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-02-22'
+
+# 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., 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 Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. 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 <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+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 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # 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 -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { 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 ;'
+
+# 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 ;;
+ *) 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 __ELF__ >/dev/null
+ 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 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # 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 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/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ 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 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ 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 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ 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 0 ;;
+ 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 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ 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 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # 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 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* 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 \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ 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 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????: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 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ 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 0 ;;
+ *: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 <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ 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 0 ;;
+ *:AIX:*:[45])
+ 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 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 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 <stdlib.h>
+ #include <unistd.h>
+
+ 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
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ 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 && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ 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 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ 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 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ # Determine whether the default compiler uses glibc.
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #if __GLIBC__ >= 2
+ LIBC=gnu
+ #else
+ LIBC=
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:3*)
+ echo i586-pc-interix3
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ 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 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ 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 ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ 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 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ 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"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ 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 0 ;;
+ 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 0 ;;
+ 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 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ 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 0 ;;
+ i*86:*:5:[78]*)
+ 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 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/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 0 ;;
+ 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 i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ 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 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*: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)
+ 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 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *: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 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ 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 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ case `uname -p` in
+ *86) UNAME_PROCESSOR=i686 ;;
+ powerpc) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *: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 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *: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 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+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 <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#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 <sys/param.h>
+ 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"); 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 <sys/param.h>
+# 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 && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# 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 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> 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/safecode/autoconf/config.sub b/safecode/autoconf/config.sub
new file mode 100755
index 0000000..9772e87
--- /dev/null
+++ b/safecode/autoconf/config.sub
@@ -0,0 +1,1489 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-02-22'
+
+# 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., 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.
+
+# Please send patches to <config-patches@gnu.org>. 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 <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+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 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # 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 0;;
+
+ * )
+ 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* | freebsd*-gnu* | netbsd*-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)
+ os=
+ basic_machine=$1
+ ;;
+ -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
+ ;;
+ -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/'`
+ ;;
+ -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] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | msp430 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ 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)
+ ;;
+
+ # 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-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* \
+ | m32r-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | msp430-* \
+ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # 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
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ 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
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ 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
+ ;;
+ nv1)
+ basic_machine=nv1-cray
+ os=-unicosmp
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ 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
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i686-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-*)
+ basic_machine=i686-`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
+ ;;
+ 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
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ 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
+ ;;
+ tic4x | c4x*)
+ basic_machine=tic4x-unknown
+ os=-coff
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ 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
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-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
+ ;;
+ 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
+ ;;
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv9 | sparcv9b)
+ 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* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -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*)
+ # 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* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -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
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -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
+ ;;
+ -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
+ ;;
+ -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
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ # 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
+ ;;
+ 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
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-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
+ ;;
+ -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
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -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 0
+
+# 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/safecode/autoconf/configure.ac b/safecode/autoconf/configure.ac
new file mode 100755
index 0000000..0de9cb0
--- /dev/null
+++ b/safecode/autoconf/configure.ac
@@ -0,0 +1,96 @@
+dnl **************************************************************************
+dnl * Initialize
+dnl **************************************************************************
+AC_INIT([[[SAFECode]]],[[[1.00]]],[dhurjati@cs.uiuc.edu])
+
+dnl Tell autoconf that the auxilliary files are actually located in
+dnl the LLVM autoconf directory, not here.
+AC_CONFIG_AUX_DIR(../../autoconf)
+
+dnl Tell autoconf that this is an LLVM project being configured
+dnl This provides the --with-llvmsrc and --with-llvmobj options
+LLVM_CONFIG_PROJECT
+
+dnl Verify that the source directory is valid
+AC_CONFIG_SRCDIR(["Makefile.common.in"])
+
+dnl Configure a common Makefile
+AC_CONFIG_FILES(Makefile.common)
+
+dnl Configure project makefiles
+dnl List every Makefile that exists within your source tree
+AC_CONFIG_MAKEFILE(Makefile)
+AC_CONFIG_MAKEFILE(lib/Makefile)
+AC_CONFIG_MAKEFILE(lib/ArrayBoundChecks/Makefile)
+AC_CONFIG_MAKEFILE(lib/ConvertUnsafeAllocas/Makefile)
+AC_CONFIG_MAKEFILE(lib/InsertPoolChecks/Makefile)
+AC_CONFIG_MAKEFILE(lib/PointerChecks/Makefile)
+AC_CONFIG_MAKEFILE(lib/StackSafety/Makefile)
+
+dnl **************************************************************************
+dnl * Determine which system we are building on
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Check for programs.
+dnl **************************************************************************
+
+AC_PATH_PROG(OMEGA, [omega], [echo omega])
+if test "$OMEGA" != "echo omega" ; then
+ AC_DEFINE([HAVE_OMEGA],[1],[Define if the Omega program is available])
+ AC_DEFINE_UNQUOTED([LLVM_PATH_OMEGA],"$OMEGA",
+ [Define to path of Omega program if found or 'echo omega' otherwise])
+fi
+
+dnl **************************************************************************
+dnl * Check for libraries.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for header files.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for typedefs, structures, and compiler characteristics.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Checks for library functions.
+dnl **************************************************************************
+
+dnl **************************************************************************
+dnl * Enable various compile-time options
+dnl **************************************************************************
+
+dnl --enable-llva-kernel: compile SAFECode for use with LLVA kernels
+AC_ARG_ENABLE(kernel,
+ AS_HELP_STRING(--enable-kernel,
+ [Use SAFECode for use with Linux Kernel (default is NO)]),
+ AC_DEFINE(LLVA_KERNEL,[[1]]),
+ )
+
+dnl **************************************************************************
+dnl * Set the location of various third-party software packages
+dnl **************************************************************************
+
+dnl Specify the location of the llvm-poolalloc project
+AC_ARG_WITH(poolalloc-srcdir,
+ AS_HELP_STRING([--with-poolalloc-srcdir],
+ [Specify location of Pool Allocation source code]),
+ AC_SUBST(poolallocsrcdir,"$withval"),
+ AC_SUBST(poolallocsrcdir,"$llvm_src/projects/llvm-poolalloc"
+ ))
+
+AC_ARG_WITH(poolalloc-objdir,
+ AS_HELP_STRING([--with-poolalloc-objdir],
+ [Specify location of Pool Allocation object code]),
+ AC_SUBST(poolallocobjdir,"$withval"),
+ AC_SUBST(poolallocobjdir,"$llvm_obj/projects/llvm-poolalloc"
+ ))
+
+dnl **************************************************************************
+dnl * Create the output files
+dnl **************************************************************************
+
+AC_CONFIG_HEADERS(include/safecode/Config/config.h)
+AC_OUTPUT
diff --git a/safecode/autoconf/install-sh b/safecode/autoconf/install-sh
new file mode 100755
index 0000000..398a88e
--- /dev/null
+++ b/safecode/autoconf/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# 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.
+#
+# 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}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ :
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=$mkdirprog
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ :
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ :
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ :
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -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 [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ :
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ :
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# 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 $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/safecode/autoconf/ltmain.sh b/safecode/autoconf/ltmain.sh
new file mode 100755
index 0000000..fe83ff4
--- /dev/null
+++ b/safecode/autoconf/ltmain.sh
@@ -0,0 +1,6290 @@
+# 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
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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., 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.
+
+# 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 "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | ${SED} 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5
+TIMESTAMP=" (1.1220 2003/04/05 19:32:58)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# 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'
+# test EBCDIC or ASCII
+case `echo A|od -x` in
+ *[Cc]1*) # EBCDIC based system
+ SP2NL="tr '\100' '\n'"
+ NL2SP="tr '\r\n' '\100\100'"
+ ;;
+ *) # Assume ASCII based system
+ SP2NL="tr '\040' '\012'"
+ NL2SP="tr '\015\012' '\040\040'"
+ ;;
+esac
+
+# NLS nuisances.
+# 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).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+: ${IFS=" "}
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$modename: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# 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.
+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 | \
+ grep -E 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 | \
+ sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'`
+ if test "X$win32_nmres" = "Ximport" ; then
+ win32_libid_type="x86 archive import"
+ else
+ win32_libid_type="x86 archive static"
+ fi
+ 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
+}
+
+# End of Shell function definitions
+#####################################
+
+# 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"
+
+ # Check whether tagname contains only valid characters
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ $echo "$progname: invalid tag name: $tagname" 1>&2
+ exit 1
+ ;;
+ 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$" < "$0" > /dev/null; then
+ taglist="$taglist $tagname"
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $0`"
+ 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) 2003 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 0
+ ;;
+
+ --config)
+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
+ # 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" < "$0"
+ done
+ exit 0
+ ;;
+
+ --debug)
+ $echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --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 0
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --preserve-dup-deps) duplicate_deps="yes" ;;
+
+ --quiet | --silent)
+ show=:
+ ;;
+
+ --tag) prevopt="--tag" prev=tag ;;
+ --tag=*)
+ set tag "$optarg" ${1+"$@"}
+ shift
+ prev=tag
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+fi
+
+# 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 1
+ 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_output=
+ arg_mode=normal
+ libobj=
+
+ 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 1
+ fi
+ arg_mode=target
+ continue
+ ;;
+
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=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, so we specify it 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 1
+ ;;
+ target)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit 1
+ ;;
+ *)
+ # 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 1
+ ;;
+ esac
+
+ # 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.
+ if test -n "$available_tags" && test -z "$tagname"; then
+ case $base_compile 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` "*) ;;
+ # 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$" < "$0" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`"
+ case "$base_compile " in
+ "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*)
+ # 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 1
+# else
+# $echo "$modename: using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+
+ 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 1
+ 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 1" 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 1" 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 "$0" "$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 1
+ fi
+ $echo $srcfile > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+
+ $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 <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+ # 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 $srcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $srcfile"
+ fi
+
+ if test ! -d "${xdir}$objdir"; then
+ $show "$mkdir ${xdir}$objdir"
+ $run $mkdir ${xdir}$objdir
+ status=$?
+ if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then
+ exit $status
+ fi
+ fi
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ command="$command -o $lobj"
+ fi
+
+ $run $rm "$lobj" "$output_obj"
+
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit 1
+ fi
+
+ 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."
+
+ $run $rm $removelist
+ exit 1
+ 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 <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+ # Allow error messages only from the first compilation.
+ suppress_output=' >/dev/null 2>&1'
+ else
+ # No PIC object so indicate it doesn't exist in the libtool
+ # object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+ 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 $srcfile"
+ else
+ command="$base_compile $srcfile $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"
+ $run $rm "$obj" "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit 1
+ fi
+
+ 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."
+
+ $run $rm $removelist
+ exit 1
+ 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 <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+ else
+ # 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 <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+ fi
+
+ $run $mv "${libobj}T" "${libobj}"
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+
+ exit 0
+ ;;
+
+ # libtool link mode
+ link | relink)
+ modename="$modename: link"
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # 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=
+
+ 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=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ prefer_static_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"
+ base_compile="$base_compile $arg"
+ 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 1
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$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 1
+ 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
+ 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 1
+ 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 1
+ 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 1
+ ;;
+ 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
+ ;;
+ *)
+ 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 1
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ 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
+ exit 1
+ 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*)
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-mingw* | *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd*)
+ # 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
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # gcc -m* arguments should be passed to the linker via $compiler_flags
+ # in order to pass architecture information to the linker
+ # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo
+ # but this is not reliable with gcc because gcc may use -mfoo to
+ # select a different linker, different libraries, etc, while
+ # -Wl,-mfoo simply passes -mfoo to the linker.
+ -m*)
+ # 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"
+ if test "$with_gcc" = "yes" ; then
+ compiler_flags="$compiler_flags $arg"
+ fi
+ 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 ;;
+
+ -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 1
+ ;;
+ 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 1
+ 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
+ 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 1
+ 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 1
+ fi
+
+ # 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 link
+ # command doesn't match the default compiler.
+ if test -n "$available_tags" && test -z "$tagname"; then
+ case $base_compile 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` "*) ;;
+ # 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$" < "$0" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`"
+ case $base_compile in
+ "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*)
+ # The compiler in $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 1
+# else
+# $echo "$modename: using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ 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
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$output_objdir"; then
+ 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 1
+ ;;
+ *.$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 duplcations 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
+ notinst_path= # paths that contain 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 1
+ ;;
+ 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
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+ continue
+ fi
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ 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
+ # Search the libtool library
+ lib="$searchdir/lib${name}.la"
+ if test -f "$lib"; then
+ found=yes
+ break
+ fi
+ 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"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ ;;
+ *)
+ $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)
+ if test "$deplibs_check_method" != pass_all; 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'" 1>&2
+ exit 1
+ 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 1
+ 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
+
+ # 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 1
+ 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 1
+ 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 1
+ 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 1
+ 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
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ 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 1
+ 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"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ 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
+ if test -n "$library_names" &&
+ { test "$prefer_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='~'
+ eval cmds=\"$extract_expsyms_cmds\"
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $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='~'
+ eval cmds=\"$old_archive_from_expsyms_cmds\"
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $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* ) 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 | grep "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="-L$inst_prefix_dir$libdir $add_dir"
+ ;;
+ 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 1
+ 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="-L$inst_prefix_dir$libdir $add_dir"
+ ;;
+ 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
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ 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 1
+ 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
+ newlib_search_path="$newlib_search_path $path"
+ path=""
+ fi
+ ;;
+ *)
+ 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
+ *" $depdepl "*) ;;
+ *) deplibs="$deplibs $depdepl" ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$deplibs $path" ;;
+ 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\"
+ 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 1
+ 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\"
+ 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 1
+ 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 1
+ 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]) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case $revision in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case $age in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ 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 1
+ 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="-compatibility_version $minor_current -current_version $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 1
+ ;;
+ 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}.*)
+ 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*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *)
+ # 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 <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $LTCC -o conftest conftest.c $deplibs
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" -ne "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $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 I believe you do not have"
+ $echo "*** because a test_compile did reveal that the linker did not use it for"
+ $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ $rm conftest
+ $LTCC -o conftest conftest.c $i
+ # Did it work?
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $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 a test_compile did reveal that the linker did not use this one"
+ $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning! Library $i is needed by this library but I was not able to"
+ $echo "*** make it link in! You will probably need to install it or some"
+ $echo "*** library that it depends on before this library will be fully"
+ $echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_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 "$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
+ # 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
+
+ # 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\"
+ 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"
+ 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
+ eval cmds=\"$export_symbols_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ 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=:
+ 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"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case $xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "$mkdir $xdir"
+ $run $mkdir "$xdir"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ # We will extract separately just the conflicting names and we will no
+ # longer touch any unique names. It is faster to leave these extract
+ # automatically by $AR in one run.
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+ if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
+ $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
+ $AR t "$xabs" | sort | uniq -cd | while read -r count name
+ do
+ i=1
+ while test "$i" -le "$count"
+ do
+ # Put our $i before any first dot (extension)
+ # Never overwrite any file
+ name_to="$name"
+ while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
+ do
+ name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
+ done
+ $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
+ $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
+ i=`expr $i + 1`
+ done
+ done
+ fi
+
+ libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+ 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 cmds=\"$module_expsym_cmds\"
+ else
+ eval cmds=\"$module_cmds\"
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval cmds=\"$archive_expsym_cmds\"
+ else
+ eval cmds=\"$archive_cmds\"
+ fi
+ fi
+
+ if test "X$skipped_export" != "X:" && len=`expr "X$cmds" : ".*"` &&
+ 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
+
+ # 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/$save_output-${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" : ".*"` &&
+ 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/$save_output-${k}.$objext
+ k=`expr $k + 1`
+ output=$output_objdir/$save_output-${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 reloadale object files
+ # after they are used.
+ i=0
+ while test "$i" -lt "$k"
+ do
+ i=`expr $i + 1`
+ delfiles="$delfiles $output_objdir/$save_output-${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 -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval cmds=\"$archive_expsym_cmds\"
+ else
+ eval cmds=\"$archive_cmds\"
+ 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"
+ $show "$cmd"
+ $run eval "$cmd" || 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 $?
+ exit 0
+ 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 1
+ 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"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case $xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "$mkdir $xdir"
+ $run $mkdir "$xdir"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ # We will extract separately just the conflicting names and we will no
+ # longer touch any unique names. It is faster to leave these extract
+ # automatically by $AR in one run.
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+ if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
+ $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
+ $AR t "$xabs" | sort | uniq -cd | while read -r count name
+ do
+ i=1
+ while test "$i" -le "$count"
+ do
+ # Put our $i before any first dot (extension)
+ # Never overwrite any file
+ name_to="$name"
+ while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
+ do
+ name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
+ done
+ $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
+ $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
+ i=`expr $i + 1`
+ done
+ done
+ fi
+
+ reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+ 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"
+ eval cmds=\"$reload_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $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 0
+ 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 0
+ 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"
+ eval cmds=\"$reload_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $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 0
+ ;;
+
+ 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
+
+ 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*)
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ 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/$output.exp"
+ $run $rm $export_symbols
+ $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ else
+ $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+ $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ 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 >/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. */
+const struct {
+ 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 -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $LTCC -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.
+ 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}%"`
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit 1
+ ;;
+ 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"
+ 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 $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 0
+ 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 $0 --fallback-echo"; then
+ case $0 in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$0 --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* )
+ cwrappersource=`$echo ${objdir}/lt-${output}.c`
+ cwrapper=`$echo ${output}.exe`
+ $rm $cwrappersource $cwrapper
+ trap "$rm $cwrappersource $cwrapper; exit 1" 1 2 15
+
+ cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable 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 executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#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 '/'
+#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
+#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 */
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+char * basename (const char *name);
+char * fnqualify(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 ((char *) basename (argv[0]));
+ newargz = XMALLOC(char *, argc+2);
+EOF
+
+ cat >> $cwrappersource <<EOF
+ newargz[0] = "$SHELL";
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+ newargz[1] = fnqualify(argv[0]);
+ /* 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;
+EOF
+
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",newargz);
+EOF
+
+ cat >> $cwrappersource <<"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
+;
+}
+
+char *
+basename (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha (name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return (char *) base;
+}
+
+char *
+fnqualify(const char *path)
+{
+ size_t size;
+ char *p;
+ char tmp[LT_PATHMAX + 1];
+
+ assert(path != NULL);
+
+ /* Is it qualified already? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha (path[0]) && path[1] == ':')
+ return xstrdup (path);
+#endif
+ if (IS_DIR_SEPARATOR (path[0]))
+ return xstrdup (path);
+
+ /* prepend the current directory */
+ /* doesn't handle '~' */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
+ p = XMALLOC(char, size);
+ sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
+ return p;
+}
+
+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 -s -o $cwrapper $cwrappersource
+ ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit 1" 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.
+if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+
+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 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 >> $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 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\
+"
+ chmod +x $output
+ fi
+ exit 0
+ ;;
+ 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"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ # Add in members from convenience archives.
+ for xlib in $addlibs; do
+ # Extract the objects.
+ case $xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "$mkdir $xdir"
+ $run $mkdir "$xdir"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ # We will extract separately just the conflicting names and we will no
+ # longer touch any unique names. It is faster to leave these extract
+ # automatically by $AR in one run.
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+ if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
+ $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
+ $AR t "$xabs" | sort | uniq -cd | while read -r count name
+ do
+ i=1
+ while test "$i" -le "$count"
+ do
+ # Put our $i before any first dot (extension)
+ # Never overwrite any file
+ name_to="$name"
+ while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
+ do
+ name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
+ done
+ $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
+ $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
+ i=`expr $i + 1`
+ done
+ done
+ fi
+
+ oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ eval cmds=\"$old_archive_from_new_cmds\"
+ else
+ eval cmds=\"$old_archive_cmds\"
+
+ if len=`expr "X$cmds" : ".*"` &&
+ 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 in parts
+ $echo "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+ # GNU ar 2.10+ was changed to match POSIX; thus no paths are
+ # encoded into archives. This makes 'ar r' malfunction in
+ # this piecewise linking case whenever conflicting object
+ # names appear in distinct ar calls; check, warn and compensate.
+ if (for obj in $save_oldobjs
+ do
+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
+ $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
+ AR_FLAGS=cq
+ fi
+ # 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" : ".*"` &&
+ 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
+ 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 $0 --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+
+ # 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 1
+ 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 1
+ 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 1
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ 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 0
+ ;;
+
+ # 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" | $Xsed | 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) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -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 1
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ 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 1
+ 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 1
+ 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 1
+ ;;
+ 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 1
+ 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 1
+ 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 1
+ 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.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ eval cmds=\"$postinstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || 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 1
+ ;;
+ 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 0
+ ;;
+
+ *)
+ # 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=
+
+ # To insure that "foo" is sourced, and not "foo.exe",
+ # finese the cygwin/MSYS system by explicitly sourcing "foo."
+ # which disallows the automatic-append-.exe behavior.
+ case $build in
+ *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+ *) wrapperdot=${wrapper} ;;
+ esac
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . ${wrapperdot} ;;
+ *) . ./${wrapperdot} ;;
+ 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 1
+ 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=
+ # To insure that "foo" is sourced, and not "foo.exe",
+ # finese the cygwin/MSYS system by explicitly sourcing "foo."
+ # which disallows the automatic-append-.exe behavior.
+ case $build in
+ *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+ *) wrapperdot=${wrapper} ;;
+ esac
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . ${wrapperdot} ;;
+ *) . ./${wrapperdot} ;;
+ esac
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir="/tmp"
+ test -n "$TMPDIR" && tmpdir="$TMPDIR"
+ tmpdir="$tmpdir/libtool-$$"
+ if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+ else
+ $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+ continue
+ fi
+ 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 anyways
+ 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 "$striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ eval cmds=\"$old_postinstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $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 $0 --finish$current_libdirs'
+ else
+ exit 0
+ 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.
+ eval cmds=\"$finish_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $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 0
+
+ $echo "----------------------------------------------------------------------"
+ $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 "----------------------------------------------------------------------"
+ exit 0
+ ;;
+
+ # 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 1
+ 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 1
+ 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 1
+ 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 1
+ 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 0
+ 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 1
+ 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"
+ test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+
+ if test "$mode" = uninstall; then
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ eval cmds=\"$postuninstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $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.
+ eval cmds=\"$old_postuninstall_cmds\"
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $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.
+ fi
+ 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 1
+ ;;
+ esac
+
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit 1
+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 <bug-libtool@gnu.org>."
+ exit 0
+ ;;
+
+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
+ -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 1
+ ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# 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:
diff --git a/safecode/autoconf/mkinstalldirs b/safecode/autoconf/mkinstalldirs
new file mode 100755
index 0000000..13752fc
--- /dev/null
+++ b/safecode/autoconf/mkinstalldirs
@@ -0,0 +1,101 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.2 2005-11-09 01:45:54 dhurjati Exp $
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case "${1}" in
+ -h | --help | --h* ) # -h for help
+ echo "${usage}" 1>&2; exit 0 ;;
+ -m ) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; }
+ dirmode="${1}"
+ shift ;;
+ -- ) shift; break ;; # stop option processing
+ -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option
+ * ) break ;; # first non-opt arg
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+0) exit 0 ;;
+esac
+
+case $dirmode in
+'')
+ if mkdir -p -- . 2>/dev/null; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ fi ;;
+*)
+ if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ 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: 3
+# End:
+# mkinstalldirs ends here
diff --git a/safecode/configure b/safecode/configure
new file mode 100755
index 0000000..e46f950
--- /dev/null
+++ b/safecode/configure
@@ -0,0 +1,2674 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59 for [SAFECode] [1.00].
+#
+# Report bugs to <dhurjati@cs.uiuc.edu>.
+#
+# Copyright (C) 2003 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 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+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+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
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; 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'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# 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
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ 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
+
+ ;;
+ 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_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # 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 before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, 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
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\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 sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+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$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# 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'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# 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`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME='[SAFECode]'
+PACKAGE_TARNAME='--safecode--'
+PACKAGE_VERSION='[1.00]'
+PACKAGE_STRING='[SAFECode] [1.00]'
+PACKAGE_BUGREPORT='dhurjati@cs.uiuc.edu'
+
+ac_unique_file=""Makefile.common.in""
+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 datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS LLVM_SRC LLVM_OBJ OMEGA poolallocsrcdir poolallocobjdir LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# 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.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+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
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -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 | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$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" ;;
+
+ -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'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ 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 ;;
+
+ -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 ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ 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 ;;
+
+ -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'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ 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; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ 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 paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+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
+
+
+# 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 its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$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
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+
+#
+# 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 [SAFECode] [1.00] 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 \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+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]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --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]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of [SAFECode] [1.00]:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-kernel Use SAFECode for use with Linux Kernel (default is
+ NO)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-llvmsrc Location of LLVM Source Code
+ --with-llvmobj Location of LLVM Object Code
+ --with-poolalloc-srcdir Specify location of Pool Allocation source code
+ --with-poolalloc-objdir Specify location of Pool Allocation object code
+
+Report bugs to <dhurjati@cs.uiuc.edu>.
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style 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
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+[SAFECode] configure [1.00]
+generated by GNU Autoconf 2.59
+
+Copyright (C) 2003 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 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by [SAFECode] $as_me [1.00], which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+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`
+hostinfo = `(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
+
+} >&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_sep=
+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_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ 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: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+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,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf 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 -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >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 -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; 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 `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; 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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+
+
+# Check whether --with-llvmsrc or --without-llvmsrc was given.
+if test "${with_llvmsrc+set}" = set; then
+ withval="$with_llvmsrc"
+ llvm_src="$withval"
+else
+ llvm_src=""
+fi;
+ LLVM_SRC=$llvm_src
+
+
+# Check whether --with-llvmobj or --without-llvmobj was given.
+if test "${with_llvmobj+set}" = set; then
+ withval="$with_llvmobj"
+ llvm_obj="$withval"
+else
+ llvm_obj=""
+fi;
+ LLVM_OBJ=$llvm_obj
+
+ ac_config_commands="$ac_config_commands setup"
+
+
+
+
+
+ ac_config_files="$ac_config_files Makefile.common"
+
+
+ ac_config_commands="$ac_config_commands Makefile"
+
+
+ ac_config_commands="$ac_config_commands lib/Makefile"
+
+
+ ac_config_commands="$ac_config_commands lib/ArrayBoundChecks/Makefile"
+
+
+ ac_config_commands="$ac_config_commands lib/ConvertUnsafeAllocas/Makefile"
+
+
+ ac_config_commands="$ac_config_commands lib/InsertPoolChecks/Makefile"
+
+
+ ac_config_commands="$ac_config_commands lib/PointerChecks/Makefile"
+
+
+ ac_config_commands="$ac_config_commands lib/StackSafety/Makefile"
+
+
+
+
+
+# Extract the first word of "omega", so it can be a program name with args.
+set dummy omega; 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_OMEGA+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $OMEGA in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_OMEGA="$OMEGA" # 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 $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_OMEGA="$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
+
+ test -z "$ac_cv_path_OMEGA" && ac_cv_path_OMEGA="echo omega"
+ ;;
+esac
+fi
+OMEGA=$ac_cv_path_OMEGA
+
+if test -n "$OMEGA"; then
+ echo "$as_me:$LINENO: result: $OMEGA" >&5
+echo "${ECHO_T}$OMEGA" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test "$OMEGA" != "echo omega" ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_OMEGA 1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define LLVM_PATH_OMEGA "$OMEGA"
+_ACEOF
+
+fi
+
+
+
+
+
+
+# Check whether --enable-kernel or --disable-kernel was given.
+if test "${enable_kernel+set}" = set; then
+ enableval="$enable_kernel"
+ cat >>confdefs.h <<\_ACEOF
+#define LLVA_KERNEL 1
+_ACEOF
+
+fi;
+
+
+
+# Check whether --with-poolalloc-srcdir or --without-poolalloc-srcdir was given.
+if test "${with_poolalloc_srcdir+set}" = set; then
+ withval="$with_poolalloc_srcdir"
+ poolallocsrcdir="$withval"
+
+else
+ poolallocsrcdir="$llvm_src/projects/llvm-poolalloc"
+
+
+fi;
+
+
+# Check whether --with-poolalloc-objdir or --without-poolalloc-objdir was given.
+if test "${with_poolalloc_objdir+set}" = set; then
+ withval="$with_poolalloc_objdir"
+ poolallocobjdir="$withval"
+
+else
+ poolallocobjdir="$llvm_obj/projects/llvm-poolalloc"
+
+
+fi;
+
+
+ ac_config_headers="$ac_config_headers include/safecode/Config/config.h"
+
+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, don't put newlines in cache variables' values.
+# 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.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *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 \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!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 "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ 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}'
+
+# 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
+
+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_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${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+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+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
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; 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'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# 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
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ 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
+
+ ;;
+ 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_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # 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 before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, 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
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+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 sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+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$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# 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'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by [SAFECode] $as_me [1.00], which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+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 <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+[SAFECode] config.status [1.00]
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_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
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+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 0 ;;
+ --debug | --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;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+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" ;;
+
+ 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 $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+llvm_src="${LLVM_SRC}"
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile.common" ) CONFIG_FILES="$CONFIG_FILES Makefile.common" ;;
+ "setup" ) CONFIG_COMMANDS="$CONFIG_COMMANDS setup" ;;
+ "Makefile" ) CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile" ;;
+ "lib/Makefile" ) CONFIG_COMMANDS="$CONFIG_COMMANDS lib/Makefile" ;;
+ "lib/ArrayBoundChecks/Makefile" ) CONFIG_COMMANDS="$CONFIG_COMMANDS lib/ArrayBoundChecks/Makefile" ;;
+ "lib/ConvertUnsafeAllocas/Makefile" ) CONFIG_COMMANDS="$CONFIG_COMMANDS lib/ConvertUnsafeAllocas/Makefile" ;;
+ "lib/InsertPoolChecks/Makefile" ) CONFIG_COMMANDS="$CONFIG_COMMANDS lib/InsertPoolChecks/Makefile" ;;
+ "lib/PointerChecks/Makefile" ) CONFIG_COMMANDS="$CONFIG_COMMANDS lib/PointerChecks/Makefile" ;;
+ "lib/StackSafety/Makefile" ) CONFIG_COMMANDS="$CONFIG_COMMANDS lib/StackSafety/Makefile" ;;
+ "include/safecode/Config/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS include/safecode/Config/config.h" ;;
+ *) { { 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 to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $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 -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# 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
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@LLVM_SRC@,$LLVM_SRC,;t t
+s,@LLVM_OBJ@,$LLVM_OBJ,;t t
+s,@OMEGA@,$OMEGA,;t t
+s,@poolallocsrcdir@,$poolallocsrcdir,;t t
+s,@poolallocobjdir@,$poolallocobjdir,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$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'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$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'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # 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. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+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,@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,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ # Do quote $f, to prevent DOS paths from being IFS'd.
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #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.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ # 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. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ 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
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$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'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$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'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+ ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+ ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_dest" : 'X\(//\)[^/]' \| \
+ X"$ac_dest" : 'X\(//\)$' \| \
+ X"$ac_dest" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$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'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+ case $ac_dest in
+ Makefile ) ${llvm_src}/autoconf/mkinstalldirs `dirname Makefile`
+ ${SHELL} ${llvm_src}/autoconf/install-sh -c ${srcdir}/Makefile Makefile ;;
+ lib/Makefile ) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/Makefile`
+ ${SHELL} ${llvm_src}/autoconf/install-sh -c ${srcdir}/lib/Makefile lib/Makefile ;;
+ lib/ArrayBoundChecks/Makefile ) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/ArrayBoundChecks/Makefile`
+ ${SHELL} ${llvm_src}/autoconf/install-sh -c ${srcdir}/lib/ArrayBoundChecks/Makefile lib/ArrayBoundChecks/Makefile ;;
+ lib/ConvertUnsafeAllocas/Makefile ) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/ConvertUnsafeAllocas/Makefile`
+ ${SHELL} ${llvm_src}/autoconf/install-sh -c ${srcdir}/lib/ConvertUnsafeAllocas/Makefile lib/ConvertUnsafeAllocas/Makefile ;;
+ lib/InsertPoolChecks/Makefile ) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/InsertPoolChecks/Makefile`
+ ${SHELL} ${llvm_src}/autoconf/install-sh -c ${srcdir}/lib/InsertPoolChecks/Makefile lib/InsertPoolChecks/Makefile ;;
+ lib/PointerChecks/Makefile ) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/PointerChecks/Makefile`
+ ${SHELL} ${llvm_src}/autoconf/install-sh -c ${srcdir}/lib/PointerChecks/Makefile lib/PointerChecks/Makefile ;;
+ lib/StackSafety/Makefile ) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/StackSafety/Makefile`
+ ${SHELL} ${llvm_src}/autoconf/install-sh -c ${srcdir}/lib/StackSafety/Makefile lib/StackSafety/Makefile ;;
+ esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (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
+
diff --git a/safecode/include/ABCPreProcess.h b/safecode/include/ABCPreProcess.h
new file mode 100755
index 0000000..43991e6
--- /dev/null
+++ b/safecode/include/ABCPreProcess.h
@@ -0,0 +1,39 @@
+#ifndef ABC_PREPROCESS_H
+#define ABC_PREPROCESS_H
+
+#include "llvm/Pass.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
+#include "AffineExpressions.h"
+namespace llvm {
+
+Pass *createABCPreProcessPass();
+
+namespace ABC {
+//This pass is written because the induction var pass doesnt run properly
+//after the phi nodes are inserted.
+ struct ABCPreProcess : public FunctionPass {
+ private:
+ PostDominanceFrontier * pdf;
+ DominanceFrontier * df;
+ DominatorSet *ds;
+ PostDominatorSet *pds;
+ virtual void print(ostream &out, const Module * M) const;
+ void indVariables(Loop *L);
+
+ public :
+ const char *getPassName() const { return "Collect Induction Variables"; }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<LoopInfo>();
+ AU.addRequired<DominatorSet>();
+ AU.addRequired<PostDominatorSet>();
+ AU.addRequired<DominanceFrontier>();
+ AU.addRequired<PostDominanceFrontier>();
+ }
+ virtual bool runOnFunction(Function &F);
+ };
+}
+
+}
+#endif
diff --git a/safecode/include/AffineExpressions.h b/safecode/include/AffineExpressions.h
new file mode 100755
index 0000000..278399b
--- /dev/null
+++ b/safecode/include/AffineExpressions.h
@@ -0,0 +1,218 @@
+//===- llvm/ArrayBoundChecks/AffineExpressions.h - Expression Analysis Utils ---*- C++ -*--=//
+//
+// This file defines a package of expression analysis utilties:
+//
+
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_C_EXPRESSIONS_H
+#define LLVM_C_EXPRESSIONS_H
+
+#include <assert.h>
+#include <map>
+#include <list>
+#include <string>
+#include "llvm/Instruction.h"
+#include "llvm/Instructions.h"
+#include "llvm/InstrTypes.h"
+#include "llvm/Constants.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/DerivedTypes.h"
+
+using namespace std;
+namespace llvm {
+
+
+namespace cfg { class LoopInfo; }
+
+typedef std::map<const PHINode *, Value *> IndVarMap;
+typedef std::map<const Function *,BasicBlock *> ExitNodeMap;
+typedef std::map<const Function *, PostDominanceFrontier *> PostDominanceFrontierMap;
+
+typedef std::map<const Value*,int> CoefficientMap;
+typedef std::map<const Value*,string> ValStringMap;
+typedef std::list<const Value*> VarList;
+typedef std::list<const Value*>::const_iterator VarListIt;
+typedef std::list<const CallInst*> CallInstList;
+typedef std::list<const CallInst*>::const_iterator CallInstListIt;
+typedef std::map<Instruction*, bool> MemAccessInstListType;
+typedef std::map<Instruction*, bool>::const_iterator MemAccessInstListIt;
+
+
+
+
+// LinearExpr - Represent an expression of the form CONST*VAR1+CONST*VAR2+ .....
+// or simpler.
+
+
+class LinearExpr {
+
+ int offSet;
+ VarList* vList;
+ CoefficientMap* cMap;
+ ValStringMap* vsMap;
+public:
+enum ExpressionType {
+ Linear, // Expr is linear
+ Unknown
+ } exprTy;
+ inline int getOffSet() { return offSet; };
+ inline void setOffSet(int offset) { offSet = offset; };
+ inline ExpressionType getExprType() { return exprTy; };
+ inline VarList* getVarList() { return vList; };
+ inline CoefficientMap* getCMap() { return cMap; };
+ inline ValStringMap* getVSMap() { return vsMap; };
+
+ LinearExpr(const Value *Val,Mangler *Mang); // Create a linear expression
+ void negate();
+ void addLinearExpr(LinearExpr *);
+ LinearExpr * mulLinearExpr(LinearExpr *);
+ void mulByConstant(int);
+ void print(ostream &out);
+ void printOmegaSymbols(ostream &out);
+};
+
+class Constraint {
+ string var;
+ LinearExpr *le;
+ string rel; // can be < , >, <=, >= for now
+ bool leConstant_; //is the left value constant
+public :
+ Constraint(string v, LinearExpr *l, string r, bool leConstant = false ) {
+ assert(l != 0 && "the rhs for this constraint is null");
+ var = v;
+ le = l;
+ rel = r;
+ leConstant_ = leConstant;
+ }
+ void print(ostream &out);
+ void printOmegaSymbols(ostream &out);
+};
+
+
+
+//This holds a set of ABCExprs
+class ABCExprTree {
+ Constraint *constraint;
+ ABCExprTree *right;
+ ABCExprTree *left;
+ string logOp; // can be && or || or
+ public:
+ ABCExprTree(Constraint *c) {
+ constraint = c;
+ left = 0;
+ right = 0;
+ logOp = "&&";
+ };
+ ABCExprTree(ABCExprTree *l, ABCExprTree *r, string op) {
+ constraint = 0;
+ // r->dump();
+ assert( l && " l is null \n");
+ assert( r && " r is null \n");
+ left = l;
+ right = r;
+ logOp = op;
+ }
+ void dump();
+ void print(ostream &out);
+ void printOmegaSymbols(ostream &out);
+};
+
+typedef std::map<const Value *, ABCExprTree *> InstConstraintMapType;
+
+
+
+//This holds the local information of a function
+class FuncLocalInfo {
+ //Local cache for constraints
+ InstConstraintMapType FuncLocalConstraints;
+
+ //Storing all constraints which need proving
+ InstConstraintMapType FuncSafetyConstraints;
+
+ //All array accesses in a function
+ MemAccessInstListType maiList;
+ //This stores the Or of the arguments at
+ //various call sites, so that can be computed only once for
+ //different array accesses.
+ ABCExprTree *argConstraints;
+public :
+ FuncLocalInfo() {
+ argConstraints = 0;
+ }
+
+ inline void addMemAccessInst(Instruction *MAI, bool reqArg) {
+ maiList[MAI] = reqArg;
+ }
+
+ inline void addLocalConstraint(const Value *v, ABCExprTree *aet) {
+ FuncLocalConstraints[v] = aet;
+ }
+ inline bool inLocalConstraints(const Value *v) {
+ return (FuncLocalConstraints.count(v) > 0);
+ }
+ inline ABCExprTree * getLocalConstraint(const Value *v) {
+ if (FuncLocalConstraints.count(v)) return FuncLocalConstraints[v];
+ else return 0;
+ }
+ inline void addSafetyConstraint(const Value *v, ABCExprTree *aet) {
+ FuncSafetyConstraints[v] = aet;
+ }
+ inline ABCExprTree* getSafetyConstraint(const Value *v) {
+ return (FuncSafetyConstraints[v]);
+ }
+ inline MemAccessInstListType getMemAccessInstList() {
+ return maiList;
+ }
+ inline void addArgumentConstraints(ABCExprTree *aet) {
+ argConstraints = aet;
+ }
+ inline ABCExprTree * getArgumentConstraints() {
+ return argConstraints;
+ }
+
+};
+
+// We dont want identifier names with ., space, - in them.
+// So we replace them with _
+static inline string makeNameProper(string x) {
+ string tmp;
+ int len = 0;
+ for (string::iterator sI = x.begin(), sEnd = x.end(); sI != sEnd; sI++) {
+ if (len > 18) return tmp; //have to do something more meaningful
+ len++;
+ switch (*sI) {
+ case '.': tmp += "d_"; len++;break;
+ case ' ': tmp += "s_"; len++;break;
+ case '-': tmp += "D_"; len++;break;
+ case '_': tmp += "l_"; len++;break;
+ default: tmp += *sI;
+ }
+ }
+ if (tmp == "in") return "in__1";
+ return tmp;
+}
+
+ /*
+static string getValueNames(const Value *V, Mangler *Mang) {
+ if (const Constant *CPI = dyn_cast<Constant>(V)) {
+ if (const ConstantSInt *CPI = dyn_cast<ConstantSInt>(V)) {
+ return itostr(CPI->getValue());
+ } else if (const ConstantUInt *CPI = dyn_cast<ConstantUInt>(V)) {
+ return utostr(CPI->getValue());
+ }
+ }
+ if (V->hasName()) {
+ return makeNameProper(V->getName());
+ }
+ else {
+ return Mang->getValueName(V);
+ }
+};
+ */
+}
+
+#endif
diff --git a/safecode/include/ArrayBoundsCheck.h b/safecode/include/ArrayBoundsCheck.h
new file mode 100755
index 0000000..5130b91
--- /dev/null
+++ b/safecode/include/ArrayBoundsCheck.h
@@ -0,0 +1,102 @@
+//Assumes that ABCPreprocess is run before
+
+#ifndef ARRAY_BOUNDS_CHECK
+#define ARRAY_BOUNDS_CHECK
+
+#include "llvm/Instruction.h"
+#include "llvm/Function.h"
+#include "AffineExpressions.h"
+#include "BottomUpCallGraph.h"
+
+namespace llvm {
+
+ModulePass *createArrayBoundsCheckPass();
+
+
+namespace ABC {
+
+struct ArrayBoundsCheck : public ModulePass {
+ public :
+ const char *getPassName() const { return "Array Bounds Check"; }
+ virtual bool runOnModule(Module &M);
+ std::vector<Instruction*> UnsafeGetElemPtrs;
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetData>();
+ AU.addRequired<CompleteBUDataStructures>();
+ AU.addRequired<BottomUpCallGraph>();
+ AU.setPreservesAll();
+ }
+ private :
+ CompleteBUDataStructures *cbudsPass;
+ BottomUpCallGraph *buCG;
+ typedef std::map<const Function *,FuncLocalInfo*> InfoMap;
+ typedef std::map<Function*, int> FuncIntMap;
+
+ //This is required for getting the names/unique identifiers for variables.
+ Mangler *Mang;
+
+ //for storing local information about a function
+ InfoMap fMap;
+
+ //Known Func Database
+ std::set<string> KnownFuncDB;
+
+ //for storing info about the functions which are already proven safe
+ FuncIntMap provenSafe;
+
+ //for storing what control dependent blocks are already dealt with for the current
+ //array access
+ std::set<BasicBlock *> DoneList;
+
+ //Initializes the KnownFuncDB
+ void initialize(Module &M);
+
+ void outputDeclsForOmega(Module &M);
+
+ //Interface for collecting constraints for different array access
+ // in a function
+ void collectSafetyConstraints(Function &F);
+
+ //This function collects from the branch which controls the current block
+ //the Successor tells the path
+ void addBranchConstraints(BranchInst *BI, BasicBlock *Successor, ABCExprTree **rootp);
+
+ //This method adds constraints for known trusted functions
+ ABCExprTree* addConstraintsForKnownFunctions(Function *kf, CallInst *CI);
+
+ //Interface for getting constraints for a particular value
+ void getConstraintsInternal( Value *v, ABCExprTree **rootp);
+ void getConstraints( Value *v, ABCExprTree **rootp);
+
+ //adds all the conditions on which the currentblock is control dependent on.
+ void addControlDependentConditions(BasicBlock *currentBlock, ABCExprTree **rootp);
+
+ //Gives the return value constraints interms of its arguments
+ ABCExprTree* getReturnValueConstraints(Function *f);
+ void getConstraintsAtCallSite(CallInst *CI,ABCExprTree **rootp);
+ void addFormalToActual(Function *f, CallInst *CI, ABCExprTree **rootp);
+
+ //Checks if the function is safe (produces output for omega consumption)
+ void checkSafety(Function &F);
+
+ //Get the constraints on the arguments
+ //This goes and looks at all call sites and ors the corresponding
+ //constraints
+ ABCExprTree* getArgumentConstraints(Function &F);
+
+ //for simplifying the constraints
+ LinearExpr* SimplifyExpression( Value *Expr, ABCExprTree **rootp);
+
+ string getValueName(const Value *V);
+ void generateArrayTypeConstraintsGlobal(string var, const ArrayType *T, ABCExprTree **rootp, unsigned int numElem);
+ void generateArrayTypeConstraints(string var, const ArrayType *T, ABCExprTree **rootp);
+ void printarraytype(string var,const ArrayType *T);
+ void printSymbolicStandardArguments(const Module *M, ostream & out);
+ void printStandardArguments(const Module *M, ostream & out);
+ void Omega(Instruction *maI, ABCExprTree *root );
+
+ };
+}
+
+}
+#endif
diff --git a/safecode/include/BottomUpCallGraph.h b/safecode/include/BottomUpCallGraph.h
new file mode 100755
index 0000000..497888e
--- /dev/null
+++ b/safecode/include/BottomUpCallGraph.h
@@ -0,0 +1,42 @@
+#ifndef BOTTOMUP_CALLGRAPH_H
+#define BOTTOMUP_CALLGRAPH_H
+#include "llvm/Pass.h"
+#include "llvm/Analysis/DataStructure/DataStructure.h"
+#include "llvm/Analysis/DataStructure/DSSupport.h"
+#include "llvm/Function.h"
+#include "llvm/Module.h"
+
+#include <set>
+
+namespace llvm {
+ struct BottomUpCallGraph : public ModulePass {
+ private:
+ // OneCalledFunction - For each indirect function call, we keep track of one
+ // the DSNode and the corresponding Call Instruction
+ typedef hash_multimap<DSNode*, CallSite> CalleeNodeCallSiteMapTy;
+ CalleeNodeCallSiteMapTy CalleeNodeCallSiteMap ;
+ std::vector<Function *> Stack;
+ std::set<Function *> Visited;
+ void figureOutSCCs(Module &M);
+ void visit(Function *f);
+
+ public:
+
+ //This keeps the map of a function and its call sites in all the callers
+ //including the indirectly called sites
+ std::map<Function *, std::vector<CallSite> > FuncCallSiteMap;
+ std::set<Function *> SccList; //Fns involved in Sccs
+
+ bool isInSCC(Function *f) {
+ return (SccList.find(f) != SccList.end());
+ }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<CompleteBUDataStructures>();
+ AU.setPreservesAll();
+ }
+ virtual bool runOnModule(Module&M);
+ };
+
+}
+#endif
diff --git a/safecode/include/ConstraintGeneration.h b/safecode/include/ConstraintGeneration.h
new file mode 100755
index 0000000..3d3cd1a
--- /dev/null
+++ b/safecode/include/ConstraintGeneration.h
@@ -0,0 +1,88 @@
+//Assumes that ABCPreprocess is run before
+#ifndef CONSTRAINT_GENERATION
+#define CONSTRAINT_GENERATION
+
+#include "llvm/Instruction.h"
+#include "llvm/Function.h"
+#include "AffineExpressions.h"
+#include "BottomUpCallGraph.h"
+
+namespace llvm {
+
+ModulePass *createConstraintGenerationPass();
+
+
+namespace ABC {
+
+struct ConstraintGeneration : public ModulePass {
+ public :
+ const char *getPassName() const { return "Interprocedural Constraint Generation"; }
+ virtual bool runOnModule(Module &M);
+ std::vector<Instruction*> UnsafeGetElemPtrs;
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetData>();
+ AU.addRequired<CompleteBUDataStructures>();
+ AU.addRequired<BottomUpCallGraph>();
+ AU.setPreservesAll();
+ }
+ private :
+ CompleteBUDataStructures *cbudsPass;
+ BottomUpCallGraph *buCG;
+
+ typedef std::map<const Function *,FuncLocalInfo*> InfoMap;
+ //This is required for getting the names/unique identifiers for variables.
+ Mangler *Mang;
+
+ //for storing local information about a function
+ InfoMap fMap;
+
+
+ //Known Func Database
+ std::set<string> KnownFuncDB;
+
+
+ //for storing what control dependent blocks are already dealt with for the current
+ //array access
+ std::set<BasicBlock *> DoneList;
+
+ //Initializes the KnownFuncDB
+ void initialize(Module &M);
+
+ //This function collects from the branch which controls the current block
+ //the Successor tells the path
+ void addBranchConstraints(BranchInst *BI, BasicBlock *Successor, ABCExprTree **rootp);
+
+ //This method adds constraints for known trusted functions
+ ABCExprTree* addConstraintsForKnownFunctions(Function *kf, CallInst *CI);
+
+ //Interface for getting constraints for a particular value
+ void getConstraintsInternal( Value *v, ABCExprTree **rootp);
+
+ //adds all the conditions on which the currentblock is control dependent on.
+ void addControlDependentConditions(BasicBlock *currentBlock, ABCExprTree **rootp);
+
+ //Gives the return value constraints interms of its arguments
+ ABCExprTree* getReturnValueConstraints(Function *f);
+ void getConstraintsAtCallSite(CallInst *CI,ABCExprTree **rootp);
+ void addFormalToActual(Function *f, CallInst *CI, ABCExprTree **rootp);
+
+ //Get the constraints on the arguments
+ //This goes and looks at all call sites and ors the corresponding
+ //constraints
+ ABCExprTree* getArgumentConstraints(Function &F);
+
+ //for simplifying the constraints
+ LinearExpr* SimplifyExpression( Value *Expr, ABCExprTree **rootp);
+
+ string getValueName(const Value *V);
+ void generateArrayTypeConstraintsGlobal(string var, const ArrayType *T, ABCExprTree **rootp, unsigned int numElem);
+ void generateArrayTypeConstraints(string var, const ArrayType *T, ABCExprTree **rootp);
+
+ public:
+ void getConstraints( Value *v, ABCExprTree **rootp);
+
+ };
+}
+
+}
+#endif
diff --git a/safecode/include/ConvertUnsafeAllocas.h b/safecode/include/ConvertUnsafeAllocas.h
new file mode 100755
index 0000000..62671ef
--- /dev/null
+++ b/safecode/include/ConvertUnsafeAllocas.h
@@ -0,0 +1,87 @@
+#ifndef CONVERT_ALLOCA_H
+#define CONVERT_ALLOCA_H
+
+#include "llvm/Pass.h"
+#include "ArrayBoundsCheck.h"
+#include "StackSafety.h"
+#include "llvm/Target/TargetData.h"
+#include "safecode/Config/config.h"
+
+namespace llvm {
+
+
+ModulePass *createConvertUnsafeAllocas();
+
+using namespace ABC;
+using namespace CSS;
+ struct MallocPass : public FunctionPass
+ {
+ private:
+inline bool changeType (Instruction * Inst);
+
+ inline bool TypeContainsPointer(const Type *Ty);
+
+ public:
+ virtual bool runOnFunction (Function &F);
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetData>();
+#ifdef LLVA_KERNEL
+ AU.setPreservesAll();
+#endif
+ }
+ };
+
+
+namespace CUA {
+struct ConvertUnsafeAllocas : public ModulePass {
+ public :
+ const char *getPassName() const { return "Array Bounds Check"; }
+ virtual bool runOnModule(Module &M);
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<ArrayBoundsCheck>();
+ AU.addRequired<checkStackSafety>();
+ AU.addRequired<CompleteBUDataStructures>();
+ AU.addRequired<TDDataStructures>();
+ AU.addRequired<TargetData>();
+ // Does not preserve the BU or TD graphs
+#ifdef LLVA_KERNEL
+ AU.setPreservesAll();
+#endif
+ }
+
+ DSNode * getDSNode(const Value *I, Function *F);
+ DSNode * getTDDSNode(const Value *I, Function *F);
+
+ std::vector<Instruction *> & getUnsafeGetElementPtrsFromABC() {
+ assert(abcPass != 0 && "First run the array bounds pass correctly");
+ return abcPass->UnsafeGetElemPtrs;
+ }
+
+ // The set of Malloc Instructions that are a result of conversion from
+ // alloca's due to static array bounds detection failure
+ std::set<const MallocInst *> ArrayMallocs;
+
+ private :
+ TDDataStructures * tddsPass;
+ BUDataStructures * budsPass;
+ ArrayBoundsCheck * abcPass;
+ checkStackSafety * cssPass;
+ TargetData *TD;
+
+#ifdef LLVA_KERNEL
+Function *kmalloc;
+#endif
+ std::list<DSNode *> unsafeAllocaNodes;
+ std::set<DSNode *> reachableAllocaNodes;
+ bool markReachableAllocas(DSNode *DSN);
+ bool markReachableAllocasInt(DSNode *DSN);
+ void TransformAllocasToMallocs(std::list<DSNode *> & unsafeAllocaNodes);
+ void TransformCSSAllocasToMallocs(std::vector<DSNode *> & cssAllocaNodes);
+ void getUnsafeAllocsFromABC();
+ void TransformCollapsedAllocas(Module &M);
+ void InsertFreesAtEnd(MallocInst *MI);
+
+};
+}
+}
+#endif
diff --git a/safecode/include/InsertPoolChecks.h b/safecode/include/InsertPoolChecks.h
new file mode 100755
index 0000000..a85eed2
--- /dev/null
+++ b/safecode/include/InsertPoolChecks.h
@@ -0,0 +1,67 @@
+#ifndef INSERT_BOUNDS_H
+#define INSERT_BOUNDS_H
+
+#include "safecode/Config/config.h"
+#include "llvm/Pass.h"
+#include "ConvertUnsafeAllocas.h"
+
+#ifndef LLVA_KERNEL
+#include "SafeDynMemAlloc.h"
+#include "poolalloc/PoolAllocate.h"
+#endif
+
+namespace llvm {
+
+ModulePass *creatInsertPoolChecks();
+using namespace CUA;
+
+struct InsertPoolChecks : public ModulePass {
+ public :
+ const char *getPassName() const { return "Inserting pool checks for array bounds "; }
+ virtual bool runOnModule(Module &M);
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<ConvertUnsafeAllocas>();
+// AU.addRequired<CompleteBUDataStructures>();
+// AU.addRequired<TDDataStructures>();
+#ifndef LLVA_KERNEL
+ AU.addRequired<EquivClassGraphs>();
+ AU.addRequired<PoolAllocate>();
+ AU.addRequired<EmbeCFreeRemoval>();
+ AU.addRequired<TargetData>();
+#else
+ AU.addRequired<TDDataStructures>();
+#endif
+
+ };
+ private :
+ CUA::ConvertUnsafeAllocas * cuaPass;
+#ifndef LLVA_KERNEL
+ PoolAllocate * paPass;
+ EquivClassGraphs *equivPass;
+ EmbeCFreeRemoval *efPass;
+ TargetData * TD;
+#else
+ TDDataStructures * TDPass;
+#endif
+ Function *PoolCheck;
+ Function *PoolCheckArray;
+ Function *ExactCheck;
+ Function *FunctionCheck;
+ void addPoolCheckProto(Module &M);
+ void addPoolChecks(Module &M);
+ void addGetElementPtrChecks(Module &M);
+ DSNode* getDSNode(const Value *V, Function *F);
+ unsigned getDSNodeOffset(const Value *V, Function *F);
+ void addLoadStoreChecks(Module &M);
+#ifndef LLVA_KERNEL
+ void addLSChecks(Value *Vnew, const Value *V, Instruction *I, Function *F);
+ Value * getPoolHandle(const Value *V, Function *F, PA::FuncInfo &FI, bool collapsed = false);
+ void registerGlobalArraysWithGlobalPools(Module &M);
+#else
+ void addLSChecks(Value *V, Instruction *I, Function *F);
+ Value * getPoolHandle(const Value *V, Function *F);
+#endif
+
+};
+}
+#endif
diff --git a/safecode/include/SafeDynMemAlloc.h b/safecode/include/SafeDynMemAlloc.h
new file mode 100755
index 0000000..bd865e0
--- /dev/null
+++ b/safecode/include/SafeDynMemAlloc.h
@@ -0,0 +1,111 @@
+//===- llvm/Transforms/IPO/EmbeC/EmbeC.h - CZero passes -*- C++ -*---------=//
+//
+// This file defines a set of utilities for EmbeC checks on pointers and
+// dynamic memory
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EMBEC_H
+#define LLVM_EMBEC_H
+
+
+#include "safecode/Config/config.h"
+#include "llvm/Pass.h"
+#include "poolalloc/PoolAllocate.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Constants.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/ADT/VectorExtras.h"
+#include "llvm/Analysis/DataStructure/DataStructure.h"
+#include "llvm/Analysis/DataStructure/DSGraph.h"
+#include "llvm/Support/Debug.h"
+#include <set>
+#include <map>
+#include <string>
+using std::set;
+using std::map;
+
+using namespace llvm;
+#ifndef LLVA_KERNEL
+using namespace PA;
+#endif
+Pass* createEmbeCFreeRemovalPass();
+
+namespace {
+ static const std::string PoolI = "poolinit";
+ static const std::string PoolA = "poolalloc";
+ static const std::string PoolF = "poolfree";
+ static const std::string PoolD = "pooldestroy";
+ static const std::string PoolMUF = "poolmakeunfreeable";
+ static const std::string PoolCh = "poolcheck";
+ static const std::string PoolAA = "poolregister";
+}
+
+namespace llvm {
+
+ struct EmbeCFreeRemoval : public ModulePass {
+
+ // The function representing 'poolmakeunfreeable'
+ Function *PoolMakeUnfreeable;
+
+ Function *PoolCheck;
+
+ bool runOnModule(Module &M);
+ std::vector<Value *> Visited;
+
+ void checkPoolSSAVarUses(Function *F, Value *V,
+ map<Value *, set<Instruction *> > &FuncAllocs,
+ map<Value *, set<Instruction *> > &FuncFrees,
+ map<Value *, set<Instruction *> > &FuncDestroy);
+
+ void propagateCollapsedInfo(Function *F, Value *V);
+ DSNode *guessDSNode(Value *v, DSGraph &G, PA::FuncInfo *PAFI);
+ void guessPoolPtrAndInsertCheck(PA::FuncInfo *PAFI, Value *oldI, Instruction *I, Value *pOpI, DSGraph &oldG);
+
+ void insertNonCollapsedChecks(Function *Forig, Function *F, DSNode *DSN);
+
+ void addRuntimeChecks(Function *F, Function *Forig);
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+#ifndef LLVA_KERNEL
+ AU.addRequired<EquivClassGraphs>();
+ AU.addRequired<PoolAllocate>();
+#endif
+ AU.addRequired<CompleteBUDataStructures>();
+ AU.addRequired<TDDataStructures>();
+ AU.addRequired<CallGraph>();
+ AU.setPreservesAll();
+ }
+
+ // Maps from a function to a set of Pool pointers and DSNodes from the
+ // original function corresponding to collapsed pools.
+ map <Function *, set<Value *> > CollapsedPoolPtrs;
+
+
+ private:
+
+ Module *CurModule;
+
+ TDDataStructures *TDDS;
+ EquivClassGraphs *BUDS;
+#ifndef LLVA_KERNEL
+ PoolAllocate *PoolInfo;
+#endif
+ bool moduleChanged;
+ bool hasError;
+
+ // The following maps are only for pool pointers that escape a function.
+ // Associates function with set of pools that are freed or alloc'ed using
+ // pool_free or pool_alloc but not destroyed within the function.
+ // These have to be pool pointer arguments to the function
+ map<Function *, set<Value *> > FuncFreedPools;
+ map<Function *, set<Value *> > FuncAllocedPools;
+ map<Function *, set<Value *> > FuncDestroyedPools;
+
+ };
+}
+
+#endif
diff --git a/safecode/include/StackSafety.h b/safecode/include/StackSafety.h
new file mode 100755
index 0000000..56fbe0e
--- /dev/null
+++ b/safecode/include/StackSafety.h
@@ -0,0 +1,38 @@
+//===- StackSafety.h -*- C++ -*---------=//
+//
+// This file defines checks for stack safety
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_STACKSAFETY_H
+#define LLVM_STACKSAFETY_H
+
+#include "llvm/Pass.h"
+#include "llvm/Analysis/DataStructure/DataStructure.h"
+#include "llvm/Analysis/DataStructure/DSGraph.h"
+#include "llvm/Analysis/DataStructure/DSNode.h"
+#include <set>
+namespace llvm {
+
+ ModulePass* createStackSafetyPass();
+
+ namespace CSS {
+
+ struct checkStackSafety : public ModulePass {
+
+ public :
+ std::vector<DSNode *> AllocaNodes;
+ const char *getPassName() const { return "Stack Safety Check";}
+ virtual bool runOnModule(Module &M);
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<CompleteBUDataStructures>();
+ AU.setPreservesAll();
+ }
+ private :
+ std::set<DSNode *> reachableAllocaNodes;
+ bool markReachableAllocas(DSNode *DSN, bool start=false);
+ bool markReachableAllocasInt(DSNode *DSN, bool start=false);
+ };
+ }
+}
+#endif
diff --git a/safecode/include/UninitPointer.h b/safecode/include/UninitPointer.h
new file mode 100755
index 0000000..2e6f11c
--- /dev/null
+++ b/safecode/include/UninitPointer.h
@@ -0,0 +1,19 @@
+//===- llvm/Transforms/IPO/CZero/CZero.h - CZero passes -*- C++ -*---------=//
+//
+// This file defines a set of utilities for CZero checks on pointers and
+// dynamic memory
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CZERO_H
+#define LLVM_CZERO_H
+
+using namespace llvm;
+
+#include "llvm/Pass.h"
+
+
+FunctionPass* createCZeroUninitPtrPass();
+// FunctionPass* createCZeroLivePtrs();
+
+#endif
diff --git a/safecode/include/omega.h b/safecode/include/omega.h
new file mode 100755
index 0000000..1967643
--- /dev/null
+++ b/safecode/include/omega.h
@@ -0,0 +1,2 @@
+int main1(int argc, char **argv);
+#define OMEGA_SAFE_VALUE 200
diff --git a/safecode/include/safecode/Config/config.h.in b/safecode/include/safecode/Config/config.h.in
new file mode 100755
index 0000000..ffe008e
--- /dev/null
+++ b/safecode/include/safecode/Config/config.h.in
@@ -0,0 +1,507 @@
+/* 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
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* 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 <alloca.h> 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 <argz.h> 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 <assert.h> 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 to 1 if you have the `closedir' function. */
+#undef HAVE_CLOSEDIR
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define to 1 if you have the <dirent.h> 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 <dld.h> 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 <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define if dlopen() is available on this platform. */
+#undef HAVE_DLOPEN
+
+/* Define to 1 if you have the <dl.h> header file. */
+#undef HAVE_DL_H
+
+/* Define if you have the _dyld_func_lookup function. */
+#undef HAVE_DYLD
+
+/* Define to 1 if you have the <errno.h> 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 <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Set to 1 if the finite function is found in <ieeefp.h> */
+#undef HAVE_FINITE_IN_IEEEFP_H
+
+/* Define to 1 if you have the `floorf' function. */
+#undef 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. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Does not have <hash_map> */
+#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 */
+#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 <inttypes.h> 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 <cmath> */
+#undef HAVE_ISINF_IN_CMATH
+
+/* Set to 1 if the isinf function is found in <math.h> */
+#undef HAVE_ISINF_IN_MATH_H
+
+/* Set to 1 if the isnan function is found in <cmath> */
+#undef HAVE_ISNAN_IN_CMATH
+
+/* Set to 1 if the isnan function is found in <math.h> */
+#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 `elf' library (-lelf). */
+#undef HAVE_LIBELF
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#undef HAVE_LIBPTHREAD
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <link.h> 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 if lt_dlopen() is available on this platform */
+#undef HAVE_LT_DLOPEN
+
+/* Define to 1 if you have the <mach-o/dyld.h> 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 <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the <malloc/malloc.h> 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 <memory.h> 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 <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the `nearbyintf' function. */
+#undef HAVE_NEARBYINTF
+
+/* 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
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Have pthread_mutex_lock */
+#undef HAVE_PTHREAD_MUTEX_LOCK
+
+/* Define to 1 if srand48/lrand48/drand48 exist in <stdlib.h> */
+#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. */
+#undef HAVE_SBRK
+
+/* 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 <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef 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 <cmath> */
+#undef HAVE_STD_ISINF_IN_CMATH
+
+/* Set to 1 if the std::isnan function is found in <cmath> */
+#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 <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> 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 `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 <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/dl.h> header file. */
+#undef HAVE_SYS_DL_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if the system has the type `uint64_t'. */
+#undef HAVE_UINT64_T
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <utime.h> 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 <windows.h> header file. */
+#undef 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
+
+/* 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
+
+/* Define if this is Unixish platform */
+#undef LLVM_ON_UNIX
+
+/* Define if this is Win32ish platform */
+#undef LLVM_ON_WIN32
+
+/* 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
+
+/* 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 run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> 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 <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* 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. */
+#undef error_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to 1 if building for use with the Linux kernel */
+#undef LLVA_KERNEL
diff --git a/safecode/include/utils/LICENSE.TXT b/safecode/include/utils/LICENSE.TXT
new file mode 100755
index 0000000..8753776
--- /dev/null
+++ b/safecode/include/utils/LICENSE.TXT
@@ -0,0 +1,6 @@
+(C) Copyright Nicolai M. Josuttis 2001.
+Permission to copy, use, modify, sell and distribute this software
+is granted provided this copyright notice appears in all copies.
+This software is provided "as is" without express or implied
+warranty, and with no claim as to its suitability for any purpose.
+
diff --git a/safecode/include/utils/fdstream.h b/safecode/include/utils/fdstream.h
new file mode 100755
index 0000000..8aad96b
--- /dev/null
+++ b/safecode/include/utils/fdstream.h
@@ -0,0 +1,180 @@
+/* The following code declares classes to read from and write to
+ * file descriptore or file handles.
+ *
+ * See
+ * http://www.josuttis.com/cppcode
+ * for details and the latest version.
+ *
+ * - open:
+ * - integrating BUFSIZ on some systems?
+ * - optimized reading of multiple characters
+ * - stream for reading AND writing
+ * - i18n
+ *
+ * (C) Copyright Nicolai M. Josuttis 2001.
+ * Permission to copy, use, modify, sell and distribute this software
+ * is granted provided this copyright notice appears in all copies.
+ * This software is provided "as is" without express or implied
+ * warranty, and with no claim as to its suitability for any purpose.
+ *
+ * Aug 05, 2001
+ */
+#ifndef BOOST_FDSTREAM_HPP
+#define BOOST_FDSTREAM_HPP
+
+#include <istream>
+#include <ostream>
+#include <streambuf>
+// for EOF:
+#include <cstdio>
+// for memcpy():
+#include <cstring>
+
+
+// low-level read and write functions
+#ifdef _MSC_VER
+# include <io.h>
+#else
+# include <unistd.h>
+//extern "C" {
+// int write (int fd, const char* buf, int num);
+// int read (int fd, char* buf, int num);
+//}
+#endif
+
+
+// BEGIN namespace BOOST
+namespace boost {
+
+
+/************************************************************
+ * fdostream
+ * - a stream that writes on a file descriptor
+ ************************************************************/
+
+
+class fdoutbuf : public std::streambuf {
+ protected:
+ int fd; // file descriptor
+ public:
+ // constructor
+ fdoutbuf (int _fd) : fd(_fd) {
+ }
+ protected:
+ // write one character
+ virtual int_type overflow (int_type c) {
+ if (c != EOF) {
+ char z = c;
+ if (write (fd, &z, 1) != 1) {
+ return EOF;
+ }
+ }
+ return c;
+ }
+ // write multiple characters
+ virtual
+ std::streamsize xsputn (const char* s,
+ std::streamsize num) {
+ return write(fd,s,num);
+ }
+};
+
+class fdostream : public std::ostream {
+ protected:
+ fdoutbuf buf;
+ public:
+ fdostream (int fd) : std::ostream(0), buf(fd) {
+ rdbuf(&buf);
+ }
+};
+
+
+/************************************************************
+ * fdistream
+ * - a stream that writes on a file descriptor
+ ************************************************************/
+
+class fdinbuf : public std::streambuf {
+ protected:
+ int fd; // file descriptor
+ protected:
+ /* data buffer:
+ * - at most, pbSize characters in putback area plus
+ * - at most, bufSize characters in ordinary read buffer
+ */
+ static const int pbSize = 4; // size of putback area
+ static const int bufSize = 1024; // size of the data buffer
+ char buffer[bufSize+pbSize]; // data buffer
+
+ public:
+ /* constructor
+ * - initialize file descriptor
+ * - initialize empty data buffer
+ * - no putback area
+ * => force underflow()
+ */
+ fdinbuf (int _fd) : fd(_fd) {
+ setg (buffer+pbSize, // beginning of putback area
+ buffer+pbSize, // read position
+ buffer+pbSize); // end position
+ }
+
+ protected:
+ // insert new characters into the buffer
+ virtual int_type underflow () {
+#ifndef _MSC_VER
+using std::memcpy;
+#endif
+
+ // is read position before end of buffer?
+ if (gptr() < egptr()) {
+ return *gptr();
+ }
+
+ /* process size of putback area
+ * - use number of characters read
+ * - but at most size of putback area
+ */
+ int numPutback;
+ numPutback = gptr() - eback();
+ if (numPutback > pbSize) {
+ numPutback = pbSize;
+ }
+
+ /* copy up to pbSize characters previously read into
+ * the putback area
+ */
+ memcpy (buffer+(pbSize-numPutback), gptr()-numPutback,
+ numPutback);
+
+ // read at most bufSize new characters
+ int num;
+ num = read (fd, buffer+pbSize, bufSize);
+ if (num <= 0) {
+ // ERROR or EOF
+ return EOF;
+ }
+
+ // reset buffer pointers
+ setg (buffer+(pbSize-numPutback), // beginning of putback area
+ buffer+pbSize, // read position
+ buffer+pbSize+num); // end of buffer
+
+ // return next character
+ return *gptr();
+ }
+};
+
+class fdistream : public std::istream {
+ protected:
+ fdinbuf buf;
+ public:
+ fdistream (int fd) : std::istream(0), buf(fd) {
+ rdbuf(&buf);
+ }
+};
+
+
+} // END namespace boost
+
+#endif /*BOOST_FDSTREAM_HPP*/
diff --git a/safecode/lib/ArrayBoundChecks/ABCPreProcess.cpp b/safecode/lib/ArrayBoundChecks/ABCPreProcess.cpp
new file mode 100755
index 0000000..b634efd
--- /dev/null
+++ b/safecode/lib/ArrayBoundChecks/ABCPreProcess.cpp
@@ -0,0 +1,110 @@
+//===- ArrayBoundCheck.cpp - ArrayBounds Checking (Omega)----------------===//
+//
+// requires piNodeinsertion pass before
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+#include "llvm/Function.h"
+#include "llvm/BasicBlock.h"
+#include "ABCPreProcess.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/Instruction.h"
+#include "llvm/Constants.h"
+
+using namespace llvm;
+using namespace ABC;
+
+IndVarMap indMap;
+DominatorSet::DomSetMapType dsmt;
+PostDominatorSet::DomSetMapType pdsmt;
+PostDominanceFrontier::DomSetMapType pdfmt;
+DominanceFrontier::DomSetMapType dfmt;
+
+void ABCPreProcess::print(ostream &out, const Module * M) const {
+ out << " Printing phi nodes which are induction variables ... \n";
+ IndVarMap::iterator ivCurrent = indMap.begin(), ivEnd = indMap.end();
+ for (; ivCurrent != ivEnd; ++ivCurrent) {
+ out << ivCurrent->first;
+ }
+ out << " Printing induction variables done ... \n";
+
+}
+
+void ABCPreProcess::indVariables(Loop *L) {
+ PHINode *PN = L->getCanonicalInductionVariable();
+ Value *V = L->getTripCount();
+ if (PN && V) {
+ indMap[PN] = V;
+ }
+ for (Loop::iterator I = L->begin(), E= L->end(); I!= E; ++I) {
+ indVariables(*I);
+ }
+}
+
+bool ABCPreProcess::runOnFunction(Function &F) {
+ LoopInfo &LI = getAnalysis<LoopInfo>();
+ pdf = &getAnalysis<PostDominanceFrontier>();
+ df = &getAnalysis<DominanceFrontier>();
+ //copy it to a global for later use by a module pass
+ PostDominanceFrontier::iterator pdfmI = pdf->begin(), pdfmE = pdf->end();
+ for (; pdfmI != pdfmE; ++pdfmI) {
+ PostDominanceFrontier::DomSetType &dst = pdfmI->second;
+ DominatorSet::DomSetType::iterator dstI = dst.begin(), dstE = dst.end();
+ for (; dstI != dstE; ++ dstI) {
+ //Could this be optimized with stl version of set copy?
+ pdfmI->first;
+ pdfmt[pdfmI->first].insert(*dstI);
+ }
+ }
+
+ //copy it to global for later use by a module pass
+ DominanceFrontier::iterator dfmI = df->begin(), dfmE = df->end();
+ for (; dfmI != dfmE; ++dfmI) {
+ DominanceFrontier::DomSetType &dst = dfmI->second;
+ DominatorSet::DomSetType::iterator dstI = dst.begin(), dstE = dst.end();
+ for (; dstI != dstE; ++ dstI) {
+ //Could this be optimized with stl version of set copy?
+ dfmI->first;
+ dfmt[dfmI->first].insert(*dstI);
+ }
+ }
+
+ ds = &getAnalysis<DominatorSet>();
+ //copy it to a global for later use by a module pass
+ DominatorSet::iterator dsmI = ds->begin(), dsmE = ds->end();
+ for (; dsmI != dsmE; ++dsmI) {
+ DominatorSet::DomSetType &dst = dsmI->second;
+ DominatorSet::DomSetType::iterator dstI = dst.begin(), dstE = dst.end();
+ for (; dstI != dstE; ++ dstI) {
+ //Could this be optimized with stl version of set copy?
+ dsmt[dsmI->first].insert(*dstI);
+ }
+ }
+
+
+ pds = &getAnalysis<PostDominatorSet>();
+ //copy it to a global for later use by a module pass
+ PostDominatorSet::iterator pdsmI = pds->begin(), pdsmE = pds->end();
+ for (; dsmI != dsmE; ++dsmI) {
+ DominatorSet::DomSetType &dst = pdsmI->second;
+ DominatorSet::DomSetType::iterator dstI = dst.begin(), dstE = dst.end();
+ for (; dstI != dstE; ++ dstI) {
+ //Could this be optimized with stl version of set copy?
+ pdsmt[pdsmI->first].insert(*dstI);
+ }
+ }
+
+
+
+ for (LoopInfo::iterator I = LI.begin(), E = LI.end(); I != E; ++I) {
+ Loop *L = *I;
+ indVariables(L);
+ }
+ return false;
+}
+
+RegisterPass<ABCPreProcess> Y("abcpre",
+ "Array Bounds Checking preprocess pass");
+
+Pass *createABCPreProcessPass() { return new ABCPreProcess(); }
diff --git a/safecode/lib/ArrayBoundChecks/AffineExpressions.cpp b/safecode/lib/ArrayBoundChecks/AffineExpressions.cpp
new file mode 100755
index 0000000..609803f
--- /dev/null
+++ b/safecode/lib/ArrayBoundChecks/AffineExpressions.cpp
@@ -0,0 +1,195 @@
+//===- Expressions.cpp - Expression Analysis Utilities ----------------------=//
+//
+// This file defines a package of expression analysis utilties:
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "AffineExpressions.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Function.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/InstrTypes.h"
+#include "llvm/BasicBlock.h"
+#include <iostream>
+
+using namespace llvm;
+
+LinearExpr::LinearExpr(const Value *Val, Mangler *Mang) {
+ if (Val) {
+ vList = new VarList();
+ cMap = new CoefficientMap();
+ vsMap = new ValStringMap();
+ if (const ConstantInt *CPI = dyn_cast<ConstantInt>(Val)) {
+ offSet = CPI->getSExtValue();
+ exprTy = Linear;
+ return;
+ } else if (const ConstantInt *CPI = dyn_cast<ConstantInt>(Val)) {
+ offSet = CPI->getSExtValue();
+ exprTy = Linear;
+ return;
+ }
+ offSet = 0;
+ vList->push_back(Val);
+ string tempstr;
+ tempstr = makeNameProper(Mang->getValueName(Val));
+ /*
+ } else {
+ int Slot = Tab.getSlot(Val); // slot number
+ if (Slot >= 0) {
+ tempstr = "l_" + itostr(Slot) + "_" + utostr(Val->getType()->getUniqueID());
+ } else {
+ exprTy = Unknown;
+ tempstr = "unknown";
+ return;
+ }
+ }
+ */
+ (*vsMap)[Val] = tempstr;
+ (*cMap)[Val] = 1;
+ }
+ else exprTy = Unknown;
+}
+
+
+void
+LinearExpr::negate() {
+ mulByConstant(-1);
+}
+
+
+void
+LinearExpr::print(ostream &out) {
+
+ if (exprTy != Unknown) {
+ VarListIt vlj = vList->begin();
+ out << offSet;
+ for (; vlj != vList->end(); ++vlj)
+ out << " + " << (*cMap)[*vlj] << " * " << (*vsMap)[*vlj];
+ } else out << "Unknown ";
+}
+
+void
+LinearExpr::printOmegaSymbols(ostream &out) {
+ if (exprTy != Unknown) {
+ VarListIt vlj = vList->begin();
+ for (; vlj != vList->end(); ++vlj)
+ out << "symbolic " << (*vsMap)[*vlj] << ";\n";
+ }
+}
+
+
+void
+LinearExpr::addLinearExpr(LinearExpr *E) {
+ if (E->getExprType() == Unknown) {
+ exprTy = Unknown;
+ return;
+ }
+ offSet = E->getOffSet() + offSet;
+ VarList* vl = E->getVarList();
+ CoefficientMap* cm = E->getCMap();
+ ValStringMap* vsm = E->getVSMap();
+
+ VarListIt vli = vl->begin();
+ bool matched;
+ for (; vli != vl->end(); ++vli) {
+ matched = false;
+ VarListIt vlj = vList->begin();
+ for (; vlj != vList->end(); ++vlj) {
+ if (*vli == *vlj) {
+ //matched the vars .. now add the coefficients.
+ (*cMap)[*vli] = (*cMap)[*vli] + (*cm)[*vlj];
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ //didnt match any var....
+ vList->push_back(*vli);
+ (*cMap)[*vli] = (*cm)[*vli];
+ (*vsMap)[*vli] = (*vsm)[*vli];
+ }
+ }
+}
+
+LinearExpr *
+LinearExpr::mulLinearExpr(LinearExpr *E) {
+ if ((exprTy == Unknown) || (E->getExprType() == Unknown)) {
+ exprTy = Unknown;
+ return this;
+ }
+ VarList* vl = E->getVarList();
+ if ((vl->size() != 0) && (vList->size() != 0)) {
+ exprTy = Unknown;
+ return this;
+ }
+ if (vl->size() == 0) {
+ //The one coming in is a constant
+ mulByConstant(E->getOffSet());
+ return this;
+ } else {
+ E->mulByConstant(offSet);
+ return E;
+ }
+}
+
+void
+LinearExpr::mulByConstant(int E) {
+ offSet = offSet * E;
+ VarListIt vlj = vList->begin();
+ for (; vlj != vList->end(); ++vlj) {
+ (*cMap)[*vlj] = (*cMap)[*vlj] * E;
+ }
+}
+
+void
+Constraint::print(ostream &out) {
+ out << var;
+ out << rel;
+ le->print(out);
+}
+
+void
+Constraint::printOmegaSymbols(ostream &out) {
+ if (!leConstant_) out << "symbolic " << var << ";\n";
+ le->printOmegaSymbols(out);
+}
+
+void
+ABCExprTree::dump() {
+ print(std::cout);
+}
+
+void
+ABCExprTree::print(ostream &out) {
+ if (constraint != 0) {
+ constraint->print(out);
+ }
+ else {
+ if (logOp == "||")
+ out << "((";
+ left->print(out);
+ if (logOp == "||")
+ out << ") ";
+ out << "\n" << logOp;
+ if (logOp == "||")
+ out << "(";
+ right->print(out);
+ if (logOp == "||")
+ out << "))";
+ }
+}
+
+void
+ABCExprTree::printOmegaSymbols(ostream &out) {
+ if (constraint != 0) {
+ constraint->printOmegaSymbols(out);
+ }
+ else {
+ left->printOmegaSymbols(out);
+ right->printOmegaSymbols(out);
+ }
+
+}
+
diff --git a/safecode/lib/ArrayBoundChecks/ArrayBoundCheck.cpp b/safecode/lib/ArrayBoundChecks/ArrayBoundCheck.cpp
new file mode 100755
index 0000000..485dfa1
--- /dev/null
+++ b/safecode/lib/ArrayBoundChecks/ArrayBoundCheck.cpp
@@ -0,0 +1,1467 @@
+//===- ArrayBoundCheck.cpp - ArrayBounds Checking (Omega)----------------===//
+//
+// Now we use the control dependence, post dominance frontier to generate constraints
+// for
+//===----------------------------------------------------------------------===//
+#include <unistd.h>
+#include "utils/fdstream.h"
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+#include "llvm/BasicBlock.h"
+#include "ArrayBoundsCheck.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Constants.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "omega.h"
+#include "llvm/ADT/VectorExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Analysis/DataStructure/DSGraph.h"
+#include "llvm/Support/CommandLine.h"
+#include <fstream>
+#include <iostream>
+#include <stdio.h>
+#include <fcntl.h>
+
+#define NO_STATIC_CHECK
+#define OMEGA_TMP_INCLUDE_FILE "omega_include.ip"
+
+using namespace llvm;
+using namespace ABC;
+
+namespace {
+ cl::opt<string> OmegaFilename("omegafile",
+ cl::desc("Specify omega include filename"),
+ cl::init(OMEGA_TMP_INCLUDE_FILE),
+ cl::value_desc("filename"));
+}
+std::ostream &Out = std::cerr;
+std::ofstream includeOut;
+
+//The following are filled from the preprocess pass, since they require
+//fn passes
+extern IndVarMap indMap;
+extern DominatorSet::DomSetMapType dsmt;
+extern PostDominatorSet::DomSetMapType pdsmt;
+extern PostDominanceFrontier::DomSetMapType pdfmt;
+
+static bool dominates(BasicBlock *bb1, BasicBlock *bb2) {
+ DominatorSet::DomSetMapType::const_iterator dsmtI = dsmt.find(bb1);
+ assert((dsmtI != dsmt.end()) && " basic block not found in dominator set");
+ return (dsmtI->second.count(bb2) != 0);
+}
+
+static bool postDominates(BasicBlock *bb1, BasicBlock *bb2) {
+ PostDominatorSet::DomSetMapType::const_iterator pdsmtI = pdsmt.find(bb1);
+ if (pdsmtI == pdsmt.end())
+ return false;
+ return (pdsmtI->second.count(bb2) != 0);
+}
+
+//count the number of problems given to Omega
+static unsigned countA = 0;
+//This will tell us whether the collection of constraints
+//depends on the incoming args or not
+//Do we need this to be global?
+static bool reqArgs = false;
+//a hack for llvm's malloc instruction which concerts all ints to uints
+//This is not really necessary, as it is checked in the pool allocation run-time
+//library
+static bool fromMalloc = false;
+
+//Interprocedural ArrayBoundsCheck pass
+RegisterPass<ArrayBoundsCheck> abc1("abc1","Array Bounds Checking pass");
+
+
+ void ArrayBoundsCheck::initialize(Module &M) {
+ KnownFuncDB.insert("snprintf"); //added the format string & string check
+ KnownFuncDB.insert("strcpy"); //need to add the extra checks
+ KnownFuncDB.insert("memcpy"); //need to add the extra checks
+ KnownFuncDB.insert("llvm.memcpy"); //need to add the extra checks
+ KnownFuncDB.insert("strlen"); //Gives return value constraints
+ KnownFuncDB.insert("read"); // read requires checks and return value constraints
+ KnownFuncDB.insert("fread"); //need to add the extra checks
+
+ KnownFuncDB.insert("fprintf"); //need to check if it is not format string
+ KnownFuncDB.insert("printf"); //need to check if it is not format string
+ KnownFuncDB.insert("vfprintf"); //need to check if it is not format string
+ KnownFuncDB.insert("syslog"); //need to check if it is not format string
+
+ KnownFuncDB.insert("memset"); //need to check if we are not setting outside
+ KnownFuncDB.insert("llvm.memset"); //need to check if we are not setting outside
+ KnownFuncDB.insert("gets"); // need to check if the char array is greater than 80
+ KnownFuncDB.insert("strchr"); //FIXME check has not been added yet
+ KnownFuncDB.insert("sprintf"); //FIXME to add extra checks
+ KnownFuncDB.insert("fscanf"); //Not sure if it requires a check
+
+ //Not sure if the following require any checks.
+ KnownFuncDB.insert("llvm.va_start");
+ KnownFuncDB.insert("llvm.va_end");
+
+ //The following doesnt require checks
+ KnownFuncDB.insert("random");
+ KnownFuncDB.insert("rand");
+ KnownFuncDB.insert("clock");
+ KnownFuncDB.insert("exp");
+ KnownFuncDB.insert("fork");
+ KnownFuncDB.insert("wait");
+ KnownFuncDB.insert("fflush");
+ KnownFuncDB.insert("fclose");
+ KnownFuncDB.insert("alarm");
+ KnownFuncDB.insert("signal");
+ KnownFuncDB.insert("setuid");
+ KnownFuncDB.insert("__errno_location");
+ KnownFuncDB.insert("log");
+ KnownFuncDB.insert("srand48");
+ KnownFuncDB.insert("drand48");
+ KnownFuncDB.insert("lrand48");
+ KnownFuncDB.insert("times");
+ KnownFuncDB.insert("puts");
+ KnownFuncDB.insert("putchar");
+ KnownFuncDB.insert("strcmp");
+ KnownFuncDB.insert("strtol");
+ KnownFuncDB.insert("fopen");
+ KnownFuncDB.insert("fwrite");
+ KnownFuncDB.insert("fgetc");
+ KnownFuncDB.insert("getc");
+ KnownFuncDB.insert("open");
+ KnownFuncDB.insert("feof");
+ KnownFuncDB.insert("fputc");
+ KnownFuncDB.insert("atol");
+ KnownFuncDB.insert("atoi");
+ KnownFuncDB.insert("atof");
+ KnownFuncDB.insert("exit");
+ KnownFuncDB.insert("perror");
+ KnownFuncDB.insert("sqrt");
+ KnownFuncDB.insert("floor");
+ KnownFuncDB.insert("pow");
+ KnownFuncDB.insert("abort");
+ KnownFuncDB.insert("srand");
+ KnownFuncDB.insert("perror");
+ KnownFuncDB.insert("__isnan");
+ KnownFuncDB.insert("__main");
+ KnownFuncDB.insert("ceil");
+ }
+
+ void ArrayBoundsCheck::outputDeclsForOmega(Module& M) {
+ for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
+ Function *F = FI;
+ includeOut << "symbolic Unknown;\n"
+ << "symbolic argc;\n"
+ << "symbolic argv;\n"
+ << "symbolic " << getValueName(F) <<"; \n";
+
+ for (Function::ArgumentListType::iterator aI=F->getArgumentList().begin(),
+ aE = F->getArgumentList().end(); aI != aE; ++aI) {
+ includeOut << "symbolic "
+ << getValueName((aI))
+ << ";\n";
+ }
+
+ for (Module::global_iterator gI = M.global_begin(), gE = M.global_end();
+ gI != gE; ++gI) {
+ includeOut << "symbolic "
+ << getValueName((gI))
+ << ";\n";
+ if (const ArrayType *AT = dyn_cast<ArrayType>(gI->getType()->getElementType())) {
+ printarraytype(getValueName(gI), AT);
+ }
+ }
+
+ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+ if ((&*I)->getType() != Type::VoidTy) {
+ includeOut << "symbolic "
+ << getValueName(&*I)
+ << ";\n";
+
+ if (AllocationInst *AI = dyn_cast<AllocationInst>(&*I)) {
+ // We have to see the dimension of the array that this alloca is
+ // pointing to
+ // If the allocation is done by constant, then its a constant array
+ // else its a normal alloca which we already have taken care of
+ if (const ArrayType *AT = dyn_cast<ArrayType>(AI->getType()->getElementType())) {
+ printarraytype(getValueName(&*I), AT);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ string ArrayBoundsCheck::getValueName(const Value *V) {
+ return Mang->getValueName(V);
+ }
+
+ void ArrayBoundsCheck::printarraytype(string var,const ArrayType *T) {
+ string var1 = var + "_i";
+ includeOut << "symbolic " << var1 << ";\n";
+ if (const ArrayType *AT = dyn_cast<ArrayType>(T->getElementType())) {
+ printarraytype(var1,AT);
+ }
+ }
+
+ABCExprTree* ArrayBoundsCheck::getReturnValueConstraints(Function *f) {
+ bool localSave = reqArgs;
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedzero = ConstantInt::get(csiType,0);
+ string var = "0";
+ Constraint *c = new Constraint(var, new LinearExpr(signedzero, Mang),"=");
+ ABCExprTree *root = new ABCExprTree(c); //dummy constraint
+ Function::iterator bI = f->begin(), bE = f->end();
+ for (;bI != bE; ++bI) {
+ BasicBlock *bb = bI;
+ if (ReturnInst *RI = dyn_cast<ReturnInst>(bb->getTerminator()))
+ getConstraints(RI,&root);
+ }
+ reqArgs = localSave ; //restore to the original
+ return root;
+}
+
+void ArrayBoundsCheck::addFormalToActual(Function *Fn, CallInst *CI, ABCExprTree **rootp) {
+ LinearExpr *le1 = new LinearExpr(CI,Mang);
+ Constraint *c1 = new Constraint(getValueName(Fn),le1,"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+
+ Function::arg_iterator formalArgCurrent = Fn->arg_begin(),
+ formalArgEnd = Fn->arg_end();
+ for (unsigned i = 1;
+ formalArgCurrent != formalArgEnd;
+ ++formalArgCurrent, ++i) {
+ string varName = getValueName(formalArgCurrent);
+ Value *OperandVal = CI->getOperand(i);
+ LinearExpr *le = new LinearExpr(OperandVal,Mang);
+ Constraint* c1 = new Constraint(varName,le,"=");
+ ABCExprTree *temp = new ABCExprTree(c1);
+ *rootp = new ABCExprTree(*rootp, temp, "&&"); //and of all arguments
+ }
+}
+
+// This is an auxillary function used by getConstraints
+// gets the constraints on the return value interms of its arguments
+// and ands it with the existing rootp!
+void ArrayBoundsCheck::getConstraintsAtCallSite(CallInst *CI,ABCExprTree **rootp) {
+ if (Function *pf = dyn_cast<Function>(CI->getOperand(0))) {
+ if (pf->isExternal()) {
+ *rootp = new ABCExprTree(*rootp,addConstraintsForKnownFunctions(pf, CI), "&&");
+ addFormalToActual(pf, CI, rootp);
+ } else {
+ if (buCG->isInSCC(pf)) {
+ std::cerr << "Ignoring return values on function in recursion\n";
+ return;
+ }
+ *rootp = new ABCExprTree(*rootp,getReturnValueConstraints(pf), "&&");
+ addFormalToActual(pf, CI, rootp);
+ }
+ //Now get the constraints on the actual arguemnts for the original call site
+ for (unsigned i =1; i < CI->getNumOperands(); ++i)
+ getConstraints(CI->getOperand(i),rootp);
+ } else {
+ //Indirect Calls
+ ABCExprTree *temproot = 0;
+ // Loop over all of the actually called functions...
+ CompleteBUDataStructures::callee_iterator I = cbudsPass->callee_begin(CI),
+ E = cbudsPass->callee_end(CI);
+ // assert((I != E) && "Indirect Call site doesn't have targets ???? ");
+ //Actually thats fine, we ignore the return value constraints ;)
+ for(; I != E; ++I) {
+ CallSite CS = CallSite::get(I->first);
+ if ((I->second->isExternal()) ||
+ (KnownFuncDB.find(I->second->getName()) != KnownFuncDB.end()) ) {
+ ABCExprTree * temp = addConstraintsForKnownFunctions(I->second, CI);
+ addFormalToActual(I->second, CI, &temp);
+ if (temproot) {
+ // We need to or them
+ temproot = new ABCExprTree(temproot, temp, "||");
+ } else {
+ temproot = temp;
+ }
+ } else {
+ if (buCG->isInSCC(I->second)) {
+ std::cerr << "Ignoring return values on function in recursion\n";
+ return;
+ }
+ ABCExprTree * temp = getReturnValueConstraints(I->second);
+ addFormalToActual(I->second, CI, &temp);
+ if (temproot) {
+ temproot = new ABCExprTree(temproot, temp, "||");
+ } else {
+ temproot = temp;
+ }
+ }
+ }
+ if (temproot) {
+ *rootp = new ABCExprTree(*rootp, temproot, "&&");
+ // Now get the constraints on the actual arguemnts for the original
+ // call site
+ for (unsigned i =1; i < CI->getNumOperands(); ++i) {
+ getConstraints(CI->getOperand(i),rootp);
+ }
+ }
+ }
+}
+
+ void ArrayBoundsCheck::addControlDependentConditions(BasicBlock *currentBlock, ABCExprTree **rootp) {
+ PostDominanceFrontier::const_iterator it = pdfmt.find(currentBlock);
+ if (it != pdfmt.end()) {
+ const PostDominanceFrontier::DomSetType &S = it->second;
+ if (S.size() > 0) {
+ PostDominanceFrontier::DomSetType::iterator pCurrent = S.begin(),
+ pEnd = S.end();
+ //check if it is control dependent on only one node.
+ //If it is control dependent on only one node.
+ //If it not, then there must be only one that dominates this node and
+ //the rest should be dominated by this node.
+ //or this must dominate every other node (incase of do while)
+ bool dominated = false;
+ bool rdominated = true; //to check if this dominates every other node
+ for (; pCurrent != pEnd; ++pCurrent) {
+ if (*pCurrent == currentBlock) {
+ rdominated = rdominated & true;
+ continue;
+ }
+ if (!dominated) {
+ if (dominates(*pCurrent, currentBlock)) {
+ dominated = true;
+ rdominated = false;
+ continue;
+ }
+ }
+ if (dominates(currentBlock, *pCurrent)) {
+ rdominated = rdominated & true;
+ continue;
+ } else {
+#if 0
+ out << "In function " << currentBlock->getParent()->getName();
+ out << "for basic block " << currentBlock->getName();
+ out << "Something wrong .. non affine or unstructured control flow ??\n";
+#endif
+ dominated = false;
+ break;
+ }
+ }
+ if ((dominated) || (rdominated)) {
+ // Now we are sure that the control dominance is proper
+ // i.e. it doesn't have unstructured control flow
+
+ PostDominanceFrontier::DomSetType::iterator pdCurrent = S.begin(),
+ pdEnd = S.end();
+ for (; pdCurrent != pdEnd; ++pdCurrent) {
+ BasicBlock *CBB = *pdCurrent;
+ if (DoneList.find(CBB) == DoneList.end()) {
+ TerminatorInst *TI = CBB->getTerminator();
+ if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
+ for (unsigned index = 0; index < BI->getNumSuccessors(); ++index) {
+ BasicBlock * succBlock = BI->getSuccessor(index);
+ if (postDominates(currentBlock, succBlock)) {
+ DoneList.insert(CBB);
+ addControlDependentConditions(CBB,rootp);
+ addBranchConstraints(BI, BI->getSuccessor(index), rootp);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // adds constraints for known functions
+ ABCExprTree* ArrayBoundsCheck::addConstraintsForKnownFunctions(Function *kf, CallInst *CI) {
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedzero = ConstantInt::get(csiType,0);
+ string var = "0";
+ Constraint *c = new Constraint(var, new LinearExpr(signedzero, Mang),"=");
+ ABCExprTree *root = new ABCExprTree(c); //dummy constraint
+ ABCExprTree **rootp = &root;
+ string funcName = kf->getName();
+ if (funcName == "memcpy") {
+ string var = getValueName(CI->getOperand(1));
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(2),Mang);
+ Constraint *c1 = new Constraint(var,l1,">=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"||");
+ getConstraints(CI->getOperand(1), rootp);
+ getConstraints(CI->getOperand(2), rootp);
+ } else if (funcName == "llvm.memcpy") {
+ string var = getValueName(CI->getOperand(1));
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(2),Mang);
+ Constraint *c1 = new Constraint(var,l1,">=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"||");
+ getConstraints(CI->getOperand(1), rootp);
+ getConstraints(CI->getOperand(2), rootp);
+ } else if (funcName == "strlen") {
+ string var = getValueName(CI);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedzero = ConstantInt::get(csiType,0);
+
+ Constraint *c = new Constraint(var, new LinearExpr(signedzero, Mang),">=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(1),Mang);
+ Constraint *c1 = new Constraint(var,l1,"<");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ getConstraints(CI->getOperand(1), rootp);
+ } else if (funcName == "read") {
+ string var = getValueName(CI);
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(3),Mang);
+ Constraint *c1 = new Constraint(var,l1,"<=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ getConstraints(CI->getOperand(3), rootp);
+
+ } else if (funcName == "fread") {
+ string var = getValueName(CI);
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(2),Mang);
+ LinearExpr *l2 = new LinearExpr(CI->getOperand(3),Mang);
+ l2->mulLinearExpr(l1);
+ Constraint *c1 = new Constraint(var,l2,"<=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ getConstraints(CI->getOperand(3), rootp);
+ getConstraints(CI->getOperand(2), rootp);
+
+ } else {
+ // out << funcName << " is not supported yet \n";
+ // Ignoring some functions is okay as long as they are not part of the
+ //one of the multiple indirect calls
+ assert((CI->getOperand(0) == kf) && "Need to handle this properly \n");
+ }
+ return root;
+ }
+
+
+ void ArrayBoundsCheck::getConstraints(Value *v, ABCExprTree **rootp) {
+ string tempName1 = getValueName(v);
+ LinearExpr *letemp1 = new LinearExpr(v,Mang);
+ Constraint* ctemp1 = new Constraint(tempName1,letemp1,"=");
+ ABCExprTree* abctemp1 = new ABCExprTree(ctemp1);
+ getConstraintsInternal(v,&abctemp1);
+ *rootp = new ABCExprTree(*rootp, abctemp1, "&&");
+ }
+
+ //Get Constraints on a value v, this assumes that the Table is correctly set
+ //for the function that is cal ling this
+ void ArrayBoundsCheck::getConstraintsInternal(Value *v, ABCExprTree **rootp) {
+ string var;
+ if ( Instruction *I = dyn_cast<Instruction>(v)) {
+
+ Function* func = I->getParent()->getParent();
+ BasicBlock * currentBlock = I->getParent();
+
+ //Here we need to add the post dominator stuff if necessary
+ addControlDependentConditions(currentBlock, rootp);
+
+ if (!isa<ReturnInst>(I)) {
+ var = getValueName(I);
+ } else {
+ var = getValueName(func);
+ }
+ if (fMap.count(func)) {
+ if (fMap[func]->inLocalConstraints(I)) { //checking the cache
+ if (fMap[func]->getLocalConstraint(I) != 0) {
+ *rootp = new ABCExprTree(*rootp, fMap[func]->getLocalConstraint(I),"&&");
+ }
+ return;
+ }
+ } else {
+ fMap[func] = new FuncLocalInfo();
+ }
+ fMap[func]->addLocalConstraint(I,0);
+ if (isa<SwitchInst>(I)) {
+ //TODO later
+ } else if (ReturnInst * ri = dyn_cast<ReturnInst>(I)) {
+ if (ri->getNumOperands() > 0) {
+ //For getting the constraints on return values
+ LinearExpr *l1 = new LinearExpr(ri->getOperand(0),Mang);
+ Constraint *c1 = new Constraint(var,l1,"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ getConstraints(ri->getOperand(0), rootp);
+ }
+
+ } else if (PHINode *p = dyn_cast<PHINode>(I)) {
+ //its a normal PhiNode
+ if (indMap.count(p) > 0) {
+ //We know that this is the canonical induction variable
+ //First get the upper bound
+ Value *UBound = indMap[p];
+ LinearExpr *l1 = new LinearExpr(UBound, Mang);
+ Constraint *c1 = new Constraint(var, l1, "<");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedzero = ConstantInt::get(csiType,0);
+ LinearExpr *l2 = new LinearExpr(signedzero, Mang);
+ Constraint *c2 = new Constraint(var, l2, ">=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c2),"&&");
+
+ getConstraints(UBound, rootp);
+
+ }
+ } else if (isa<CallInst>(I)) {
+ CallInst * CI = dyn_cast<CallInst>(I);
+ //First we have to check if it is an RMalloc
+ if (CI->getOperand(0)->getName() == "RMalloc") {
+ //It is an RMalloc, we knoe it has only one argument
+ Constraint *c = new Constraint(var, SimplifyExpression(I->getOperand(1),rootp),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ } else {
+ if (fMap.count(func) == 0) {
+ fMap[func] = new FuncLocalInfo();
+ }
+ //This also get constraints for arguments of CI
+ getConstraintsAtCallSite(CI, rootp);
+ }
+ }
+ else if (isa<AllocationInst>(I)) {
+ //Note that this is for the local variables which are converted in to
+ //allocas, mallocs , we take care of the RMallocs (CASES work)in the CallInst case
+ AllocationInst *AI = cast<AllocationInst>(I);
+ if (const ArrayType *AT = dyn_cast<ArrayType>(AI->getType()->getElementType())) {
+ //sometime allocas have some array as their allocating constant !!
+ //We then have to generate constraints for all the dimensions
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,1);
+
+ Constraint *c = new Constraint(var, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ generateArrayTypeConstraints(var, AT, rootp);
+ } else {
+ //This is the general case, where the allocas/mallocs are allocated by some
+ //variable
+ //Ugly hack because of the llvm front end's cast of
+ //argument of malloc to uint
+ fromMalloc = true;
+ Value *sizeVal = I->getOperand(0) ;
+ // if (CastInst *csI = dyn_cast<CastInst>(I->getOperand(0))) {
+ // const Type *toType = csI->getType();
+ // const Type *fromType = csI->getOperand(0)->getType();
+ // if ((toType->isPrimitiveType()) && (toType->getPrimitiveID() == Type::UIntTyID)) {
+ // sizeVal = csI->getOperand(0);
+ // }
+ // }
+ Constraint *c = new Constraint(var, SimplifyExpression(sizeVal,rootp),"=");
+ fromMalloc = false;
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ } else if (isa<GetElementPtrInst>(I)) {
+
+
+ GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
+ Value *PointerOperand = I->getOperand(0);
+ if (const PointerType *pType = dyn_cast<PointerType>(PointerOperand->getType()) ){
+ //this is for arrays inside structs
+ if (const StructType *stype = dyn_cast<StructType>(pType->getElementType())) {
+ //getelementptr *key, long 0, ubyte 0, long 18
+ if (GEP->getNumOperands() == 4) {
+ if (const ArrayType *aType = dyn_cast<ArrayType>(stype->getContainedType(0))) {
+ int elSize = aType->getNumElements();
+ if (const ConstantInt *CSI = dyn_cast<ConstantInt>(I->getOperand(3))) {
+ elSize = elSize - CSI->getSExtValue();
+ if (elSize == 0) {
+ //Dirty HACK, this doesnt work for more than 2 arrays in a struct!!
+ if (const ArrayType *aType2 = dyn_cast<ArrayType>(stype->getContainedType(1))) {
+ elSize = aType2->getNumElements();
+ }
+ }
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,elSize);
+ Constraint *c = new Constraint(var, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ }
+ }
+ }
+ }
+ //dunno if this is a special case or need to be generalized
+ //FIXME for now it is a special case.
+ if (I->getNumOperands() == 2) {
+ getConstraints(PointerOperand,rootp);
+ getConstraints(GEP->getOperand(1),rootp);
+ LinearExpr *L1 = new LinearExpr(GEP->getOperand(1), Mang);
+ LinearExpr *L2 = new LinearExpr(PointerOperand, Mang);
+ L1->negate();
+ L1->addLinearExpr(L2);
+ Constraint *c = new Constraint(var, L1,"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ //This is added for the special case found in the embedded bench marks
+ //Normally GetElementPtrInst is taken care by the getSafetyConstraints
+ //But sometimes you get a pointer to an array x = &x[0]
+ //z = getelementptr x 0 0
+ //getlelementptr z is equivalent to getelementptr x !
+ if (I->getNumOperands() == 3) {
+ if (const PointerType *PT = dyn_cast<PointerType>(PointerOperand->getType())) {
+ if (const ArrayType *AT = dyn_cast<ArrayType>(PT->getElementType())) {
+ if (const ConstantInt *CSI = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ if (CSI->getSExtValue() == 0) {
+ if (const ConstantInt *CSI2 = dyn_cast<ConstantInt>(I->getOperand(2))) {
+ if (CSI2->getSExtValue() == 0) {
+ //Now add the constraint
+
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,AT->getNumElements());
+ Constraint *c = new Constraint(var, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ Constraint *c = new Constraint(var, SimplifyExpression(I,rootp),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ fMap[func]->addLocalConstraint(I,*rootp); //storing in the cache
+ } else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(v)) {
+ //Its a global variable...
+ //It could be an array
+ var = getValueName(GV);
+ if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) {
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,1);
+
+ Constraint *c = new Constraint(var, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ generateArrayTypeConstraintsGlobal(var, AT, rootp, 1);
+ }
+ }
+ }
+
+ void ArrayBoundsCheck::generateArrayTypeConstraintsGlobal(string var, const ArrayType *T, ABCExprTree **rootp, unsigned int numElem) {
+ string var1 = var + "_i";
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ if (const ArrayType *AT = dyn_cast<ArrayType>(T->getElementType())) {
+ const ConstantInt * signedOne = ConstantInt::get(csiType,1);
+ Constraint *c = new Constraint(var1, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ generateArrayTypeConstraintsGlobal(var1,AT, rootp, T->getNumElements() * numElem);
+ } else {
+ const ConstantInt * signedOne = ConstantInt::get(csiType,numElem * T->getNumElements());
+ Constraint *c = new Constraint(var1, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ }
+
+
+ void ArrayBoundsCheck::generateArrayTypeConstraints(string var, const ArrayType *T, ABCExprTree **rootp) {
+ string var1 = var + "_i";
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,T->getNumElements());
+ Constraint *c = new Constraint(var1, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ if (const ArrayType *AT = dyn_cast<ArrayType>(T->getElementType())) {
+ generateArrayTypeConstraints(var1,AT, rootp);
+ } else if (const StructType *ST = dyn_cast<StructType>(T->getElementType())) {
+ //This will only work one level of arrays and structs
+ //If there are arrays inside a struct then this will
+ //not help us prove the safety of the access ....
+ unsigned Size = getAnalysis<TargetData>().getTypeSize(ST);
+ string var2 = var1 + "_i";
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,Size);
+ Constraint *c = new Constraint(var2, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ }
+
+ABCExprTree *ArrayBoundsCheck::getArgumentConstraints(Function & F) {
+ if (buCG->isInSCC(&F)) return 0; //Ignore recursion for now
+ std::set<Function *> reqArgFList;
+ bool localSave = reqArgs;
+ //First check if it is in cache
+ ABCExprTree *root = fMap[&F]->getArgumentConstraints();
+ if (root) {
+ return root;
+ } else {
+ //Its not there in cache, so we compute it
+ if (buCG->FuncCallSiteMap.count(&F)) {
+ std::vector<CallSite> &cslist = buCG->FuncCallSiteMap[&F];
+ for (unsigned idx = 0, sz = cslist.size(); idx != sz; ++idx) {
+ ABCExprTree *rootCallInst = 0;
+ if (CallInst *CI = dyn_cast<CallInst>(cslist[idx].getInstruction())) {
+ //we need to AND the constraints on the arguments
+ reqArgs = false;
+ Function::arg_iterator formalArgCurrent = F.arg_begin(), formalArgEnd = F.arg_end();
+ for (unsigned i = 1; formalArgCurrent != formalArgEnd; ++formalArgCurrent, ++i) {
+ if (i < CI->getNumOperands()) {
+ string varName = getValueName(formalArgCurrent);
+ Value *OperandVal = CI->getOperand(i);
+ LinearExpr *le = new LinearExpr(OperandVal,Mang);
+ Constraint* c1 = new Constraint(varName,le,"=");
+ ABCExprTree *temp = new ABCExprTree(c1);
+ if (!isa<Constant>(OperandVal)) {
+ getConstraints(OperandVal,&temp);
+ }
+ if (!rootCallInst) {
+ rootCallInst = temp;
+ } else {
+ rootCallInst = new ABCExprTree(rootCallInst, temp, "&&");
+ }
+ }
+ }
+ if (reqArgs) {
+ //This Call site requires args better to maintain a set
+ //and get the argument constraints once for all
+ //since there could be multiple call sites from the same function
+ reqArgFList.insert(CI->getParent()->getParent());
+ }
+ }
+ if (!root) root = rootCallInst;
+ else {
+ root = new ABCExprTree(root, rootCallInst, "||");
+ }
+ }
+ std::set<Function *>::iterator sI = reqArgFList.begin(), sE= reqArgFList.end();
+ for (; sI != sE ; ++sI) {
+ ABCExprTree * argConstraints = getArgumentConstraints(**sI);
+ if (argConstraints) root = new ABCExprTree(root, argConstraints, "&&");
+ }
+ fMap[&F]->addArgumentConstraints(root); //store it in cache
+ }
+ }
+ reqArgs = localSave;
+ return root;
+ }
+
+
+ void ArrayBoundsCheck::printStandardArguments(const Module *M, ostream & out) {
+ for (Module::const_iterator fI = M->begin(), fE = M->end(); fI != fE; ++fI) {
+ if (fI->getName() == "main") {
+ Function::const_arg_iterator formalArgCurrent = fI->arg_begin(), formalArgEnd = fI->arg_end();
+ if (formalArgCurrent != formalArgEnd) {
+ //relyingon front end's ability to get two arguments
+ string argcname = getValueName(formalArgCurrent);
+ ++formalArgCurrent;
+ string argvname = getValueName(formalArgCurrent);
+ out << " && " << argcname << " = " << argvname ;
+ break;
+ }
+ }
+ }
+ }
+
+ void ArrayBoundsCheck::printSymbolicStandardArguments(const Module *M, ostream & out) {
+ for (Module::const_iterator fI = M->begin(), fE = M->end(); fI != fE; ++fI) {
+ if (fI->getName() == "main") {
+ Function::const_arg_iterator formalArgCurrent = fI->arg_begin(), formalArgEnd = fI->arg_end();
+ if (formalArgCurrent != formalArgEnd) {
+ //relyingon front end's ability to get two arguments
+ string argcname = getValueName(formalArgCurrent);//->getName();
+ ++formalArgCurrent;
+ string argvname = getValueName(formalArgCurrent);//->getName();
+ out << "symbolic " << argcname << ";\n";
+ out << "symbolic " << argvname << ";\n";
+ break;
+ }
+ }
+ }
+ }
+
+
+ //FIXME doesn't handle any kind of recursion
+ void ArrayBoundsCheck::checkSafety(Function &F) {
+ if (F.isExternal()) return;
+ if (fMap[&F] != 0) {
+ MemAccessInstListType MemAccessInstList = fMap[&F]->getMemAccessInstList();
+ MemAccessInstListIt maI = MemAccessInstList.begin(), maE = MemAccessInstList.end();
+ for (; maI != maE; ++maI) {
+ ABCExprTree *root = fMap[&F]->getSafetyConstraint(maI->first);
+ ABCExprTree * argConstraints = 0;
+ if (maI->second) {
+ argConstraints = getArgumentConstraints(F);
+ }
+ if (argConstraints) {
+ root = new ABCExprTree(root,argConstraints,"&&");
+ }
+ //omega stuff should go in here.
+ Omega(maI->first,root);
+ }
+ }
+ }
+
+#define parentR p2cdes[0]
+#define childW p2cdes[1]
+#define childR c2pdes[0]
+#define parentW c2pdes[1]
+
+void ArrayBoundsCheck::Omega(Instruction *maI, ABCExprTree *root ) {
+ int p2cdes[2];
+ int c2pdes[2];
+ pid_t pid;
+ pipe(p2cdes);
+ pipe(c2pdes);
+
+
+ if ((pid = fork())) {
+ //this is the parent
+ close(childR);
+ close(childW);
+ fcntl(parentW, F_SETFL, O_NONBLOCK);
+ boost::fdostream out(parentW);
+ const Module *M = (maI)->getParent()->getParent()->getParent();
+ if (root != 0) {
+ root->printOmegaSymbols(out);
+ DEBUG(root->printOmegaSymbols(std::cerr));
+ }
+ printSymbolicStandardArguments(M, out);
+
+ //Dinakar Debug
+ DEBUG(printSymbolicStandardArguments(M,std::cerr));
+
+ out << " P" <<countA << " := {[i] : \n";
+
+ //Dinakar Debug
+ DEBUG(std::cerr << " P" << countA << " := {[i] : \n");
+
+ if (root != 0)root->print(out);
+ //Dinakar Debug
+ DEBUG(if (root != 0)root->print(std::cerr));
+
+ printStandardArguments(M, out);
+ //Dinakar Debug
+ DEBUG(printStandardArguments(M, std::cerr));
+ // out << " && (argv = argc) ";
+ out << "};\n Hull P"<<countA++ << ";\n" ;
+
+ //Dinakar Debug
+ DEBUG(std::cerr << "};\n Hull P"<<countA-1 << ";\n");
+ close(parentW);
+ int perl2parent[2];
+ pipe(perl2parent);
+ if (!fork()){
+ //child
+ close(perl2parent[0]); //perl doesn't read anything from parent
+ close(fileno(stdout));
+ dup(perl2parent[1]);
+ close(fileno(stdin));
+ dup(parentR); //this for reading from omega calculator
+ if (execvp("/home/vadve/dhurjati/bin/omega.pl",NULL) == -1) {
+ perror("execve error \n");
+ exit(-1);
+ }
+ } else {
+ int result;
+ close(perl2parent[1]);
+ boost::fdistream inp(perl2parent[0]);
+ std::cerr << "waiting for output " << countA << "\n";
+ inp >> result;
+ close(perl2parent[0]);
+ // read(perl2parent[0],&result,4);
+ if (result == 1) {
+ std::cerr << "proved safe \n";
+ std::cerr << maI;
+ // UnsafeGetElemPtrs.push_back(maI);
+ //Omega proved SAFE
+ } else {
+ std::cerr << "cannot prove safe " << countA;
+ std::cerr << maI;
+ UnsafeGetElemPtrs.push_back(maI);
+ }
+ }
+ } else if (pid < 0) {
+ perror("fork error \n");
+ exit(-1);
+ } else {
+ //pid == 0
+ // this is child
+ close(parentW);
+ close(parentR);
+ close(fileno(stdin));
+ dup(childR);
+ close(fileno(stdout));
+ dup(childW);
+ if (execvp("/home/vadve/dhurjati/bin/oc",NULL) == -1) {
+ perror("execve error \n");
+ exit(-1);
+ }
+ }
+}
+
+bool ArrayBoundsCheck::runOnModule(Module &M) {
+ cbudsPass = &getAnalysis<CompleteBUDataStructures>();
+ buCG = &getAnalysis<BottomUpCallGraph>();
+ Mang = new Mangler(M);
+
+ initialize(M);
+ /* printing preliminaries */
+ includeOut.open (OmegaFilename.c_str());
+ outputDeclsForOmega(M);
+ includeOut.close();
+ // out << "outputting decls for Omega done" <<endl;
+
+
+ // out << " First Collect Safety Constraints ";
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ Function &F = *I;
+ if (!(F.hasName()) || (KnownFuncDB.find(F.getName()) == KnownFuncDB.end()))
+ collectSafetyConstraints(F);
+ }
+#ifndef NO_STATIC_CHECK
+ // out << " Now checking the constraints \n ";
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ if (!(provenSafe.count(I) != 0)) checkSafety(*I);
+ }
+#endif
+ return false;
+}
+
+
+void ArrayBoundsCheck::collectSafetyConstraints(Function &F) {
+ if (fMap.count(&F) == 0) {
+ fMap[&F] = new FuncLocalInfo();
+ }
+
+ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+ Instruction *iLocal = &*I;
+ if (isa<CastInst>(iLocal)) {
+ //Some times
+ if (isa<GetElementPtrInst>(iLocal->getOperand(0))) {
+ iLocal = cast<Instruction>(iLocal->getOperand(0));
+ }
+ }
+ if (isa<GetElementPtrInst>(iLocal)) {
+ GetElementPtrInst *MAI = cast<GetElementPtrInst>(iLocal);
+
+ if (const PointerType *PT = dyn_cast<PointerType>(MAI->getPointerOperand()->getType())) {
+ if (!isa<StructType>(PT->getElementType())) {
+ User::op_iterator mI = MAI->op_begin(), mE = MAI->op_end();
+ if (mI == mE) {
+ continue;
+ }
+#ifdef NO_STATIC_CHECK
+ UnsafeGetElemPtrs.push_back(MAI);
+ continue;
+#endif
+ mI++;
+ ABCExprTree *root;
+ string varName = getValueName(MAI->getPointerOperand());
+ LinearExpr *le = new LinearExpr(*mI,Mang);
+ Constraint* c1 = new Constraint(varName,le,"<="); // length < index
+ ABCExprTree* abctemp1 = new ABCExprTree(c1);
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > index
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ root = new ABCExprTree(abctemp1, abctemp2, "||");
+ mI++;
+ for (; mI != mE; ++mI) {
+ LinearExpr *le = new LinearExpr(*mI,Mang);
+ varName = varName+"_i" ;
+ Constraint* c1 = new Constraint(varName,le,"<="); // length < index
+ ABCExprTree* abctemp1 = new ABCExprTree(c1);
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > index
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ ABCExprTree*abctempor = new ABCExprTree(abctemp1,abctemp2,"||"); // abctemp1 || abctemp2
+ root = new ABCExprTree(root, abctempor, "||");
+ // }
+ }
+ //reinitialize mI , now getting the constraints on the indices
+ //We need to clear DoneList since we are getting constraints for a
+ //new access. (DoneList is the list of basic blocks that are in the
+ //post dominance frontier of this accesses basic block
+ DoneList.clear();
+ reqArgs = false;
+ addControlDependentConditions(MAI->getParent(), &root);
+ mI = MAI->idx_begin();
+ for (; mI != mE; ++mI) {
+ getConstraints(*mI,&root);
+ }
+ getConstraints(MAI->getPointerOperand(),&root);
+ fMap[&F]->addSafetyConstraint(MAI,root);
+ fMap[&F]->addMemAccessInst(MAI, reqArgs);
+ }
+ }
+ } else if (CallInst *CI = dyn_cast<CallInst>(iLocal)) {
+ //Now we need to collect and add the constraints for trusted lib
+ //functions like read , fread, memcpy
+ if (Function *FCI = dyn_cast<Function>(CI->getOperand(0))) {
+ //Its a direct function call,
+ string funcName = FCI->getName();
+ DEBUG(std::cerr << "Adding constraints for " << funcName << "\n");
+ reqArgs = false;
+#ifdef NO_STATIC_CHECK
+ UnsafeGetElemPtrs.push_back(CI);
+ continue;
+#endif
+ if (funcName == "read") {
+ LinearExpr *le = new LinearExpr(CI->getOperand(3),Mang);
+ string varName = getValueName(CI->getOperand(2));
+ Constraint* c1 = new Constraint(varName,le,">"); // buf.length >= size
+ ABCExprTree* root = new ABCExprTree(c1);
+
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > size
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ root = new ABCExprTree(root,abctemp2,"||"); // abctemp1 || abctemp2
+ getConstraints(CI->getOperand(2), &root);
+ getConstraints(CI->getOperand(3), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+ } else if (funcName == "strchr") {
+ std::cerr << " DID NOT HANDLE strchr\n";
+ std::cerr << "Program may not be SAFE\n";
+ // exit(-1);
+ } else if (funcName == "sprintf") {
+ std::cerr << " DID NOT HANDLE sprintf\n";
+ std::cerr << "Program may not be SAFE\n";
+ // abort();
+ } else if (funcName == "fscanf") {
+ std::cerr << " DID NOT HANDLE fscanf\n";
+ std::cerr << "Program may not be SAFE\n";
+ // abort();
+ } else if (funcName == "fread") {
+ //FIXME, assumes reading only a byte
+ LinearExpr *le = new LinearExpr(CI->getOperand(3),Mang);
+ string varName = getValueName(CI->getOperand(1));
+ Constraint* c1 = new Constraint(varName,le,">"); // buf.length >= size
+ ABCExprTree* root = new ABCExprTree(c1);
+
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > size
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ root = new ABCExprTree(root,abctemp2,"||"); // abctemp1 || abctemp2
+ getConstraints(CI->getOperand(1), &root);
+ getConstraints(CI->getOperand(3), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+ } else if (funcName == "memset") {
+ LinearExpr *le = new LinearExpr(CI->getOperand(3),Mang);
+ string varName = getValueName(CI->getOperand(1));
+ Constraint* c1 = new Constraint(varName,le,">"); // buf.length >= size
+ ABCExprTree* root = new ABCExprTree(c1);
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > size
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ root = new ABCExprTree(root,abctemp2,"||"); // abctemp1 || abctemp2
+ getConstraints(CI->getOperand(1), &root);
+ getConstraints(CI->getOperand(3), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+
+ } else if (funcName == "gets") {
+ LinearExpr *le = new LinearExpr(CI->getOperand(1),Mang); //buf.length
+ Constraint* c1 = new Constraint("80",le,"<"); // buf.length > 80
+ ABCExprTree* root = new ABCExprTree(c1);
+ // Constraint* c2 = new Constraint("0",le,">",true); // 0 > size
+ // ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ // root = new ABCExprTree(root,abctemp2,"||"); // abctemp1 || abctemp2
+ getConstraints(CI->getOperand(1), &root);
+ // getConstraints(CI->getOperand(3), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+
+
+ } else if (funcName == "llvm.memset") {
+ LinearExpr *le = new LinearExpr(CI->getOperand(3),Mang);
+ string varName = getValueName(CI->getOperand(1));
+ Constraint* c1 = new Constraint(varName,le,">"); // buf.length >= size
+ ABCExprTree* root = new ABCExprTree(c1);
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > size
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ root = new ABCExprTree(root,abctemp2,"||"); // abctemp1 || abctemp2
+ getConstraints(CI->getOperand(1), &root);
+ getConstraints(CI->getOperand(3), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+
+
+ } else if (funcName == "memcpy") {
+ LinearExpr *le = new LinearExpr(CI->getOperand(3),Mang);
+ string varName = getValueName(CI->getOperand(1));
+ Constraint* c1 = new Constraint(varName,le,">"); // buf.length >= size
+ ABCExprTree* root = new ABCExprTree(c1);
+
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > size
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ root = new ABCExprTree(root,abctemp2,"||"); // abctemp1 || abctemp2
+ getConstraints(CI->getOperand(1), &root);
+ getConstraints(CI->getOperand(3), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+
+ } else if (funcName == "llvm.memcpy") {
+ LinearExpr *le = new LinearExpr(CI->getOperand(3),Mang);
+ string varName = getValueName(CI->getOperand(1));
+ Constraint* c1 = new Constraint(varName,le,">"); // buf.length >= size
+ ABCExprTree* root = new ABCExprTree(c1);
+
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > size
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ root = new ABCExprTree(root,abctemp2,"||"); // abctemp1 || abctemp2
+ getConstraints(CI->getOperand(1), &root);
+ getConstraints(CI->getOperand(3), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+
+ } else if (funcName == "strcpy") {
+ LinearExpr *le = new LinearExpr(CI->getOperand(2),Mang);
+ string varName = getValueName(CI->getOperand(1));
+ Constraint* c1 = new Constraint(varName,le,"<="); // buf.length >= size
+ ABCExprTree* root = new ABCExprTree(c1);
+
+ getConstraints(CI->getOperand(2), &root);
+ getConstraints(CI->getOperand(1), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+
+ } else if (funcName == "snprintf") {
+ LinearExpr *le = new LinearExpr(CI->getOperand(2),Mang);
+ string varName = getValueName(CI->getOperand(1));
+ Constraint* c1 = new Constraint(varName,le,">"); // buf.length >= size
+ ABCExprTree* root = new ABCExprTree(c1);
+
+ Constraint* c2 = new Constraint("0",le,">",true); // 0 > size
+ ABCExprTree* abctemp2 = new ABCExprTree(c2);
+ root = new ABCExprTree(root,abctemp2,"||"); // abctemp1 || abctemp2
+ getConstraints(CI->getOperand(1), &root);
+ getConstraints(CI->getOperand(2), &root);
+ fMap[&F]->addMemAccessInst(CI, reqArgs);
+ fMap[&F]->addSafetyConstraint(CI, root);
+
+ } else if (funcName == "fprintf") {
+ if (!isa<ConstantArray>(CI->getOperand(2))) {
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(CI->getOperand(2))) {
+ if (!isa<ConstantArray>(GEPI->getPointerOperand())) {
+ std::cerr << "Format string problem " << CI->getOperand(2);
+ //exit(-1);
+ }
+ }
+ }
+ } else if (funcName == "vfprintf") {
+ if (!isa<ConstantArray>(CI->getOperand(2))) {
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(CI->getOperand(2))) {
+ if (!isa<ConstantArray>(GEPI->getPointerOperand())) {
+ std::cerr << "Format string problem " << CI->getOperand(2);
+ // exit(-1);
+ }
+ }
+ }
+ } else if (funcName == "printf") {
+ if (!isa<ConstantArray>(CI->getOperand(1))) {
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(CI->getOperand(1))) {
+ if (!isa<ConstantArray>(GEPI->getPointerOperand())) {
+ std::cerr << "Format string problem " << CI->getOperand(1);
+ //exit(-1);
+ }
+ }
+ }
+ } else if (funcName == "syslog") {
+ if (!isa<ConstantArray>(CI->getOperand(2))) {
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(CI->getOperand(1))) {
+ if (!isa<ConstantArray>(GEPI->getPointerOperand())) {
+ std::cerr << "Format string problem " << CI->getOperand(1);
+ //exit(-1);
+ }
+ }
+ }
+ } else if (FCI->isExternal()) {
+ if (KnownFuncDB.find(funcName) == KnownFuncDB.end()) {
+ // std::cerr << "Don't know what constraints to add " << funcName << "\n";
+ // std::cerr << "Exiting \n";
+ // exit(-1);
+ }
+ }
+ } else {
+ //indirect function call doesn't call the known external functions
+ CompleteBUDataStructures::callee_iterator
+ cI = cbudsPass->callee_begin(CI), cE = cbudsPass->callee_end(CI);
+ for (; cI != cE; ++cI) {
+ if ((cI->second->isExternal()) || (KnownFuncDB.find(cI->second->getName()) != KnownFuncDB.end())) {
+ assert(1 && " Assumption that indirect fn call doesnt call an externalfails");
+ }
+ }
+ }
+ }
+ }
+}
+
+void ArrayBoundsCheck::addBranchConstraints(BranchInst *BI,BasicBlock *Successor, ABCExprTree **rootp) {
+ //this has to be a conditional branch, otherwise we wouldnt have been here
+ assert((BI->isConditional()) && "abcd wrong branch constraint");
+ if (SetCondInst *SCI = dyn_cast<SetCondInst>(BI->getCondition())) {
+
+ //SCI now has the conditional statement
+ Value *operand0 = SCI->getOperand(0);
+ Value *operand1 = SCI->getOperand(1);
+
+ getConstraints(operand0,rootp);
+ getConstraints(operand1,rootp);
+
+
+ LinearExpr *l1 = new LinearExpr(operand1,Mang);
+
+ string var0 = getValueName(operand0);
+ Constraint *ct = 0;
+
+ switch(SCI->getOpcode()) {
+ case Instruction::SetLE :
+ //there are 2 cases for each opcode!
+ //its the true branch or the false branch
+ if (BI->getSuccessor(0) == Successor) {
+ //true branch
+ ct = new Constraint(var0,l1,"<=");
+ } else {
+ ct = new Constraint(var0,l1,">");
+ }
+ break;
+ case Instruction::SetGE :
+ if (BI->getSuccessor(0) == Successor) {
+ //true branch
+ ct = new Constraint(var0,l1,">=");
+ } else {
+ //false branch
+ ct = new Constraint(var0,l1,"<");
+ }
+ break;
+ case Instruction::SetLT :
+ if (BI->getSuccessor(0) == Successor) {
+ //true branch
+ ct = new Constraint(var0,l1,"<");
+ } else {
+ //false branch
+ ct = new Constraint(var0,l1,">=");
+ }
+ break;
+ case Instruction::SetGT :
+ if (BI->getSuccessor(0) == Successor) {
+ //true branch
+ ct = new Constraint(var0,l1,">");
+ } else {
+ //false branch
+ ct = new Constraint(var0,l1,"<=");
+ }
+ break;
+ default :
+ break;
+ }
+ if (ct != 0) {
+ ct->print(std::cerr);
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(ct),"&&");
+ }
+ }
+}
+
+
+
+// SimplifyExpression: Simplify a Value and return it as an affine expressions
+LinearExpr* ArrayBoundsCheck::SimplifyExpression( Value *Expr, ABCExprTree **rootp) {
+ assert(Expr != 0 && "Can't classify a null expression!");
+ if (Expr->getType() == Type::FloatTy || Expr->getType() == Type::DoubleTy)
+ return new LinearExpr(Expr, Mang) ; // nothing known return variable itself
+
+ if ((isa<BasicBlock>(Expr)) || (isa<Function>(Expr)))
+ assert(1 && "Unexpected expression type to classify!");
+ if ((isa<GlobalVariable>(Expr)) || (isa<Argument>(Expr))) {
+ reqArgs = true; //I know using global is ugly, fix this later
+ return new LinearExpr(Expr, Mang);
+ }
+ if (isa<Constant>(Expr)) {
+ Constant *CPV = cast<Constant>(Expr);
+ if (CPV->getType()->isIntegral()) { // It's an integral constant!
+ if (dyn_cast<ConstantArray>(CPV)) {
+ assert(1 && "Constant Array don't know how to get the values ");
+ } else if (ConstantInt *CPI = dyn_cast<ConstantInt>(Expr)) {
+ return new LinearExpr(CPI, Mang);
+ }
+ }
+ return new LinearExpr(Expr, Mang); //nothing known, just return itself
+ }
+ if (isa<Instruction>(Expr)) {
+ Instruction *I = cast<Instruction>(Expr);
+
+ switch (I->getOpcode()) { // Handle each instruction type seperately
+ case Instruction::Add: {
+ LinearExpr* Left = (SimplifyExpression(I->getOperand(0), rootp));
+ if (Left == 0) {
+ Left = new LinearExpr(I->getOperand(0), Mang);
+ }
+ LinearExpr* Right = (SimplifyExpression(I->getOperand(1), rootp));
+ if (Right == 0) {
+ Right = new LinearExpr(I->getOperand(1), Mang);
+ }
+ Left->addLinearExpr(Right);
+ return Left;
+ }
+ case Instruction::Sub: {
+ LinearExpr* Left = (SimplifyExpression(I->getOperand(0), rootp));
+ if (Left == 0) {
+ Left = new LinearExpr(I->getOperand(0), Mang);
+ }
+ LinearExpr* Right = (SimplifyExpression(I->getOperand(1), rootp));
+ if (Right == 0) {
+ Right = new LinearExpr(I->getOperand(1), Mang);
+ }
+ Right->negate();
+ Left->addLinearExpr(Right);
+ return Left;
+ }
+ case Instruction::SetLE :
+ case Instruction::SetNE :
+ case Instruction::SetEQ :
+ case Instruction::SetGE :
+ case Instruction::SetLT :
+ case Instruction::SetGT : {
+ LinearExpr* L = new LinearExpr(I->getOperand(1),Mang);
+ return L;
+ };
+ case Instruction::Mul :
+
+ LinearExpr* Left = (SimplifyExpression(I->getOperand(0),rootp));
+ if (Left == 0) {
+ Left = new LinearExpr(I->getOperand(0), Mang);
+ }
+ LinearExpr* Right = (SimplifyExpression(I->getOperand(1),rootp));
+ if (Right == 0) {
+ Right = new LinearExpr(I->getOperand(1), Mang);
+ }
+ return Left->mulLinearExpr(Right);
+ } // end switch
+ if (isa<CastInst>(I)) {
+ DEBUG(std::cerr << "dealing with cast instruction ");
+ const Type *fromType = I->getOperand(0)->getType();
+ const Type *toType = I->getType();
+ string number1;
+ string number2;
+ bool addC = false;
+ if (toType->isPrimitiveType() && fromType->isPrimitiveType()) {
+ //Here we have to give constraints for
+ //FIXME .. this should be for all types not just sbyte
+ switch(toType->getTypeID()) {
+ case Type::IntTyID :
+ switch (fromType->getTypeID()) {
+ case Type::SByteTyID :
+ number1 = "-128";
+ number2 = "127";
+ addC = true;
+ break;
+ case Type::UByteTyID :
+ number1 = "0";
+ number2 = "255";
+ addC = true;
+ default:
+ break;
+ }
+ case Type::UIntTyID :
+ switch(fromType->getTypeID()) {
+ case Type::IntTyID :
+ //in llvm front end the malloc argument is always casted to
+ //uint! so we hack it here
+ //This hack works incorrectly for
+ //some programs so moved it to malloc itself
+ //FIXME FIXME This might give incorrect results in some cases!!!!
+ addC = true;
+ break;
+ case Type::SByteTyID :
+ case Type::UByteTyID :
+ number1 = "0";
+ number2 = "255";
+ addC = true;
+ break;
+ default :
+ break;
+ }
+ default:
+ break;
+ }
+ if (addC) {
+ string var = getValueName(I);
+ LinearExpr *l1 = new LinearExpr(I,Mang);
+ if (number1 != "") {
+ Constraint *c1 = new Constraint(number1,l1,">=",true);
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ }
+ if (number2 != "") {
+ Constraint *c2 = new Constraint(number2,l1,"<=",true);
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c2),"&&");
+ }
+ Constraint *c = new Constraint(var, SimplifyExpression(I->getOperand(0),rootp),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ return l1;
+ }
+ } else {
+ if (const PointerType *pType = dyn_cast<PointerType>(I->getType())){
+ const Type *eltype = pType->getElementType();
+ if (eltype->isPrimitiveType()) {
+ unsigned numbytes = 0;
+ if (eltype->getTypeID() == Type::SByteTyID) {
+ //FIXME: this should make use of Target!!!!
+ numbytes = 1;
+ } else if (eltype->getTypeID() == Type::UByteTyID) {
+ numbytes = 4;
+ } else if (eltype->getTypeID() == Type::IntTyID) {
+ numbytes = 4;
+ } else if (eltype->getTypeID() == Type::UIntTyID) {
+ numbytes = 4;
+ } else if (eltype->getTypeID() == Type::ShortTyID) {
+ numbytes = 2;
+ } else if (eltype->getTypeID() == Type::UShortTyID) {
+ numbytes = 2;
+ } else if (eltype->getTypeID() == Type::LongTyID) {
+ numbytes = 8;
+ } else if (eltype->getTypeID() == Type::ULongTyID) {
+ numbytes = 8;
+ }
+
+ if (numbytes != 0) {
+ if (const PointerType *opPType = dyn_cast<PointerType>(fromType)){
+ const Type *opEltype = opPType->getElementType();
+ if (const StructType *stype = dyn_cast<StructType>(opEltype)) {
+ //special case for casts to beginning of structs
+ // the case is (sbyte*) (Struct with the first element arrauy)
+ //If it is a cast from struct to something else * ...
+ if (const ArrayType *aType = dyn_cast<ArrayType>(stype->getContainedType(0))) {
+ if (aType->getElementType()->isPrimitiveType()) {
+ int elSize = aType->getNumElements();
+ switch (aType->getElementType()->getTypeID()) {
+ case Type::ShortTyID :
+ case Type::UShortTyID : elSize = (elSize/numbytes)*2; break;
+ case Type::IntTyID :
+ case Type::UIntTyID : elSize = (elSize/numbytes)*4; break;
+ case Type::LongTyID :
+ case Type::ULongTyID : elSize = (elSize/numbytes)*8; break;
+ default : break;
+ }
+ string varName = getValueName(I);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,elSize);
+ LinearExpr *l1 = new LinearExpr(signedOne, Mang);
+ return l1;
+ }
+ }
+ } else if (const ArrayType *aType = dyn_cast<ArrayType>(opEltype)) {
+ if (aType->getElementType()->isPrimitiveType()) {
+ int elSize = aType->getNumElements();
+ switch (aType->getElementType()->getTypeID()) {
+ case Type::SByteTyID :
+ case Type::UByteTyID : elSize = elSize / numbytes; break;
+ case Type::ShortTyID :
+ case Type::UShortTyID : elSize = (elSize/numbytes) *2; break;
+ case Type::IntTyID :
+ case Type::UIntTyID : elSize = (elSize/numbytes)*4; break;
+ case Type::LongTyID :
+ case Type::ULongTyID : elSize = (elSize/numbytes)*8; break;
+ default : break;
+ }
+ string varName = getValueName(I);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,elSize);
+ LinearExpr *l1 = new LinearExpr(signedOne, Mang);
+ return l1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return SimplifyExpression(I->getOperand(0),rootp);
+ } else {
+ getConstraints(I,rootp);
+ LinearExpr* ret = new LinearExpr(I,Mang);
+ return ret;
+ }
+ }
+ // Otherwise, I don't know anything about this value!
+ return 0;
+}
+
+
+Pass *createArrayBoundsCheckPass() { return new ABC::ArrayBoundsCheck(); }
diff --git a/safecode/lib/ArrayBoundChecks/BottomUpCallGraph.cpp b/safecode/lib/ArrayBoundChecks/BottomUpCallGraph.cpp
new file mode 100755
index 0000000..b125040
--- /dev/null
+++ b/safecode/lib/ArrayBoundChecks/BottomUpCallGraph.cpp
@@ -0,0 +1,101 @@
+#include "llvm/Analysis/DataStructure/DSGraph.h"
+#include "llvm/Analysis/DataStructure/DSNode.h"
+#include "BottomUpCallGraph.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/CallSite.h"
+#include <iostream>
+
+using namespace llvm;
+
+//This is needed because some call sites get merged away during DSA if they have
+//the same inputs for instance.
+//But for array bounds checking we need to get constraints from all the call sites
+//So we have to get them some how.
+
+bool BottomUpCallGraph::runOnModule(Module &M) {
+ CompleteBUDataStructures &CBU = getAnalysis<CompleteBUDataStructures>();
+ const CompleteBUDataStructures::ActualCalleesTy &AC = CBU.getActualCallees();
+
+ for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
+ for (inst_iterator I = inst_begin(MI), E = inst_end(MI); I != E; ++I) {
+ if (Instruction *CI = dyn_cast<Instruction>(&*I)) {
+ if (isa<CallInst>(CI)) {
+ CompleteBUDataStructures::callee_iterator cI = CBU.callee_begin(CI),
+ cE = CBU.callee_end(CI);
+ if (cI == cE) {
+ //Hmm this call site is not included in the cbuds
+ //so we need to extra stuff.
+ CallSite CS = CallSite::get(CI);
+ if (Function *FCI = dyn_cast<Function>(CI->getOperand(0))) {
+ //if it is a direct call, we can just add it!
+ FuncCallSiteMap[FCI].push_back(CS);
+ } else {
+ //Here comes the ugly part
+ Function *parenFunc = CI->getParent()->getParent();
+ DSNode *calleeNode = CBU.getDSGraph(*parenFunc).getNodeForValue(CS.getCalledValue()).getNode();
+ CalleeNodeCallSiteMap.insert(std::make_pair(calleeNode, CS));
+ }
+ }
+ }
+ }
+ }
+
+ for (CompleteBUDataStructures::ActualCalleesTy::const_iterator I = AC.begin(),
+ E = AC.end(); I != E; ++I) {
+ CallSite CS = CallSite::get(I->first);
+ DEBUG(std::cerr << "CALLEE: " << I->second->getName() << " from : " << I->first);
+ FuncCallSiteMap[I->second].push_back(CS);
+ //see if this is equivalent to any other callsites of this function.....
+ //FIXME This is very expensive way of doing it,
+ Function *parenFunc = I->first->getParent()->getParent();
+ DSNode *calleeNode = CBU.getDSGraph(*parenFunc).getNodeForValue(CS.getCalledValue()).getNode();
+ CalleeNodeCallSiteMapTy::const_iterator cI, cE;
+ tie(cI, cE) = CalleeNodeCallSiteMap.equal_range(calleeNode);
+ for (; cI != cE; ++cI) {
+ //all the call sites I->second should also be added to the funccallsitemap
+ FuncCallSiteMap[I->second].push_back(cI->second);
+ }
+ }
+ figureOutSCCs(M);
+ return false;
+}
+
+
+void BottomUpCallGraph::visit(Function *f) {
+ if (Visited.find(f) == Visited.end()) {
+ //Have not visited it before
+ Visited.insert(f);
+ //not visited implies it won't be there on the stack anyways, so push it
+ //on stack
+ Stack.push_back(f);
+ if (FuncCallSiteMap.count(f)) {
+ std::vector<CallSite> & callsitelist = FuncCallSiteMap[f];
+ for (unsigned idx = 0, sz = callsitelist.size(); idx != sz; ++idx) {
+ Function *parent = callsitelist[idx].getInstruction()->getParent()->getParent();
+ visit(parent);
+ }
+ }
+ Stack.pop_back();
+ } else {
+ //Have already visited it, check if it forms SCC
+ std::vector<Function*>::iterator res = std::find(Stack.begin(), Stack.end(), f);
+ if (res != Stack.end()) {
+ //Cycle detected.
+ for (; res != Stack.end() ; ++res) {
+ SccList.insert(*res);
+ }
+ }
+ }
+}
+
+void BottomUpCallGraph::figureOutSCCs(Module &M) {
+ for (Module::iterator I = M.begin(), E= M.end(); I != E ; ++I) {
+ visit(I);
+ }
+}
+
+ RegisterPass<BottomUpCallGraph> bucg("bucg","Call Graph from CBUDS");
diff --git a/safecode/lib/ArrayBoundChecks/ConstraintGeneration.cpp b/safecode/lib/ArrayBoundChecks/ConstraintGeneration.cpp
new file mode 100755
index 0000000..04060f8
--- /dev/null
+++ b/safecode/lib/ArrayBoundChecks/ConstraintGeneration.cpp
@@ -0,0 +1,911 @@
+//===- ConstraintGeneration.cpp for Interprocedural Constraint Generation----------------===//
+//
+// Now we use the control dependence, post dominance frontier to generate constraints
+// for
+//===----------------------------------------------------------------------===//
+#include <unistd.h>
+#include "utils/fdstream.h"
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Constants.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/ADT/VectorExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Analysis/DataStructure/DSGraph.h"
+#include "ConstraintGeneration.h"
+#include <fstream>
+#include <iostream>
+#include <stdio.h>
+#include <fcntl.h>
+
+using namespace llvm;
+using namespace ABC;
+
+//The following are filled from the preprocess pass, since they require
+//fn passes
+extern IndVarMap indMap;
+extern DominatorSet::DomSetMapType dsmt;
+extern PostDominatorSet::DomSetMapType pdsmt;
+extern PostDominanceFrontier::DomSetMapType pdfmt;
+
+static bool dominates(BasicBlock *bb1, BasicBlock *bb2) {
+ DominatorSet::DomSetMapType::const_iterator dsmtI = dsmt.find(bb1);
+ assert((dsmtI != dsmt.end()) && " basic block not found in dominator set");
+ return (dsmtI->second.count(bb2) != 0);
+}
+
+static bool postDominates(BasicBlock *bb1, BasicBlock *bb2) {
+ PostDominatorSet::DomSetMapType::const_iterator pdsmtI = pdsmt.find(bb1);
+ assert((pdsmtI != pdsmt.end()) &&
+ " basic block not found in post dominator set");
+ return (pdsmtI->second.count(bb2) != 0);
+}
+
+//This will tell us whether the collection of constraints
+//depends on the incoming args or not
+//Do we need this to be global?
+static bool reqArgs = false;
+//a hack for llvm's malloc instruction which concerts all ints to uints
+//This is not really necessary, as it is checked in the pool allocation run-time
+//library
+static bool fromMalloc = false;
+
+//Interprocedural ConstraintGeneration pass
+RegisterPass<ConstraintGeneration> cgen1("cgen","Array Bounds Checking pass");
+
+
+ void ConstraintGeneration::initialize(Module &M) {
+ KnownFuncDB.insert("snprintf"); //added the format string & string check
+ KnownFuncDB.insert("strcpy"); //need to add the extra checks
+ KnownFuncDB.insert("memcpy"); //need to add the extra checks
+ KnownFuncDB.insert("llvm.memcpy"); //need to add the extra checks
+ KnownFuncDB.insert("strlen"); //Gives return value constraints
+ KnownFuncDB.insert("read"); // read requires checks and return value constraints
+ KnownFuncDB.insert("fread"); //need to add the extra checks
+
+ KnownFuncDB.insert("fprintf"); //need to check if it is not format string
+ KnownFuncDB.insert("printf"); //need to check if it is not format string
+ KnownFuncDB.insert("vfprintf"); //need to check if it is not format string
+ KnownFuncDB.insert("syslog"); //need to check if it is not format string
+
+ KnownFuncDB.insert("memset"); //need to check if we are not setting outside
+ KnownFuncDB.insert("llvm.memset"); //need to check if we are not setting outside
+ KnownFuncDB.insert("gets"); // need to check if the char array is greater than 80
+ KnownFuncDB.insert("strchr"); //FIXME check has not been added yet
+ KnownFuncDB.insert("sprintf"); //FIXME to add extra checks
+ KnownFuncDB.insert("fscanf"); //Not sure if it requires a check
+
+ //Not sure if the following require any checks.
+ KnownFuncDB.insert("llvm.va_start");
+ KnownFuncDB.insert("llvm.va_end");
+
+ //The following doesnt require checks
+ KnownFuncDB.insert("random");
+ KnownFuncDB.insert("rand");
+ KnownFuncDB.insert("clock");
+ KnownFuncDB.insert("exp");
+ KnownFuncDB.insert("fork");
+ KnownFuncDB.insert("wait");
+ KnownFuncDB.insert("fflush");
+ KnownFuncDB.insert("fclose");
+ KnownFuncDB.insert("alarm");
+ KnownFuncDB.insert("signal");
+ KnownFuncDB.insert("setuid");
+ KnownFuncDB.insert("__errno_location");
+ KnownFuncDB.insert("log");
+ KnownFuncDB.insert("srand48");
+ KnownFuncDB.insert("drand48");
+ KnownFuncDB.insert("lrand48");
+ KnownFuncDB.insert("times");
+ KnownFuncDB.insert("puts");
+ KnownFuncDB.insert("putchar");
+ KnownFuncDB.insert("strcmp");
+ KnownFuncDB.insert("strtol");
+ KnownFuncDB.insert("fopen");
+ KnownFuncDB.insert("fwrite");
+ KnownFuncDB.insert("fgetc");
+ KnownFuncDB.insert("getc");
+ KnownFuncDB.insert("open");
+ KnownFuncDB.insert("feof");
+ KnownFuncDB.insert("fputc");
+ KnownFuncDB.insert("atol");
+ KnownFuncDB.insert("atoi");
+ KnownFuncDB.insert("atof");
+ KnownFuncDB.insert("exit");
+ KnownFuncDB.insert("perror");
+ KnownFuncDB.insert("sqrt");
+ KnownFuncDB.insert("floor");
+ KnownFuncDB.insert("pow");
+ KnownFuncDB.insert("abort");
+ KnownFuncDB.insert("srand");
+ KnownFuncDB.insert("perror");
+ KnownFuncDB.insert("__isnan");
+ KnownFuncDB.insert("__main");
+ KnownFuncDB.insert("ceil");
+ }
+
+string ConstraintGeneration::getValueName(const Value *V) {
+ return Mang->getValueName(V);
+}
+
+ABCExprTree* ConstraintGeneration::getReturnValueConstraints(Function *f) {
+ bool localSave = reqArgs;
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedzero = ConstantInt::get(csiType,0);
+ string var = "0";
+ Constraint *c = new Constraint(var, new LinearExpr(signedzero, Mang),"=");
+ ABCExprTree *root = new ABCExprTree(c); //dummy constraint
+ Function::iterator bI = f->begin(), bE = f->end();
+ for (;bI != bE; ++bI) {
+ BasicBlock *bb = bI;
+ if (ReturnInst *RI = dyn_cast<ReturnInst>(bb->getTerminator()))
+ getConstraints(RI,&root);
+ }
+ reqArgs = localSave ; //restore to the original
+ return root;
+}
+
+void ConstraintGeneration::addFormalToActual(Function *Fn, CallInst *CI, ABCExprTree **rootp) {
+ LinearExpr *le1 = new LinearExpr(CI,Mang);
+ Constraint *c1 = new Constraint(getValueName(Fn),le1,"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+
+ Function::arg_iterator formalArgCurrent = Fn->arg_begin(), formalArgEnd = Fn->arg_end();
+ for (unsigned i = 1; formalArgCurrent != formalArgEnd; ++formalArgCurrent, ++i) {
+ string varName = getValueName(formalArgCurrent);
+ Value *OperandVal = CI->getOperand(i);
+ LinearExpr *le = new LinearExpr(OperandVal,Mang);
+ Constraint* c1 = new Constraint(varName,le,"=");
+ ABCExprTree *temp = new ABCExprTree(c1);
+ *rootp = new ABCExprTree(*rootp, temp, "&&"); //and of all arguments
+ }
+}
+
+//This is an auxillary function used by getConstraints
+//gets the constraints on the return value interms of its arguments
+// and ands it with the existing rootp!
+void ConstraintGeneration::getConstraintsAtCallSite(CallInst *CI,ABCExprTree **rootp) {
+ if (Function *pf = dyn_cast<Function>(CI->getOperand(0))) {
+ if (pf->isExternal()) {
+ *rootp = new ABCExprTree(*rootp,addConstraintsForKnownFunctions(pf, CI), "&&");
+ addFormalToActual(pf, CI, rootp);
+ } else {
+ if (buCG->isInSCC(pf)) {
+ std::cerr << "Ignoring return values on function in recursion\n";
+ return;
+ }
+ *rootp = new ABCExprTree(*rootp,getReturnValueConstraints(pf), "&&");
+ addFormalToActual(pf, CI, rootp);
+ }
+ //Now get the constraints on the actual arguemnts for the original call site
+ for (unsigned i =1; i < CI->getNumOperands(); ++i)
+ getConstraints(CI->getOperand(i),rootp);
+ } else {
+ //Indirect Calls
+ ABCExprTree *temproot = 0;
+ // Loop over all of the actually called functions...
+ CompleteBUDataStructures::callee_iterator I = cbudsPass->callee_begin(CI),
+ E = cbudsPass->callee_end(CI);
+ //assert((I != E) && "Indirect Call site doesn't have targets ???? ");
+ //Actually thats fine, we ignore the return value constraints ;)
+ for(; I != E; ++I) {
+ CallSite CS = CallSite::get(I->first);
+ if ((I->second->isExternal())
+ || (KnownFuncDB.find(I->second->getName()) != KnownFuncDB.end()) ) {
+ ABCExprTree * temp = addConstraintsForKnownFunctions(I->second, CI);
+ addFormalToActual(I->second, CI, &temp);
+ if (temproot) {
+ temproot = new ABCExprTree(temproot, temp, "||"); //we need to or them
+ } else {
+ temproot = temp;
+ }
+ } else {
+ if (buCG->isInSCC(I->second)) {
+ std::cerr << "Ignoring return values on function in recursion\n";
+ return;
+ }
+ ABCExprTree * temp = getReturnValueConstraints(I->second);
+ addFormalToActual(I->second, CI, &temp);
+ if (temproot) {
+ temproot = new ABCExprTree(temproot, temp, "||");
+ } else {
+ temproot = temp;
+ }
+ }
+ }
+ if (temproot) {
+ *rootp = new ABCExprTree(*rootp, temproot, "&&");
+ //Now get the constraints on the actual arguemnts for the original call site
+ for (unsigned i =1; i < CI->getNumOperands(); ++i) {
+ getConstraints(CI->getOperand(i),rootp);
+ }
+ }
+ }
+}
+
+ void ConstraintGeneration::addControlDependentConditions(BasicBlock *currentBlock, ABCExprTree **rootp) {
+ PostDominanceFrontier::const_iterator it = pdfmt.find(currentBlock);
+ if (it != pdfmt.end()) {
+ const PostDominanceFrontier::DomSetType &S = it->second;
+ if (S.size() > 0) {
+ PostDominanceFrontier::DomSetType::iterator pCurrent = S.begin(), pEnd = S.end();
+ //check if it is control dependent on only one node.
+ //If it is control dependent on only one node.
+ //If it not, then there must be only one that dominates this node and
+ //the rest should be dominated by this node.
+ //or this must dominate every other node (incase of do while)
+ bool dominated = false;
+ bool rdominated = true; //to check if this dominates every other node
+ for (; pCurrent != pEnd; ++pCurrent) {
+ if (*pCurrent == currentBlock) {
+ rdominated = rdominated & true;
+ continue;
+ }
+ if (!dominated) {
+ if (dominates(*pCurrent, currentBlock)) {
+ dominated = true;
+ rdominated = false;
+ continue;
+ }
+ }
+ if (dominates(currentBlock, *pCurrent)) {
+ rdominated = rdominated & true;
+ continue;
+ } else {
+ // out << "In function " << currentBlock->getParent()->getName();
+ // out << "for basic block " << currentBlock->getName();
+ // out << "Something wrong .. non affine or unstructured control flow ??\n";
+ dominated = false;
+ break;
+ }
+ }
+ if ((dominated) || (rdominated)) {
+ //Now we are sure that the control dominance is proper
+ //i.e. it doesn't have unstructured control flow
+
+ PostDominanceFrontier::DomSetType::iterator pdCurrent = S.begin(), pdEnd = S.end();
+ for (; pdCurrent != pdEnd; ++pdCurrent) {
+ BasicBlock *CBB = *pdCurrent;
+ if (DoneList.find(CBB) == DoneList.end()) {
+ TerminatorInst *TI = CBB->getTerminator();
+ if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
+ for (unsigned index = 0; index < BI->getNumSuccessors(); ++index) {
+ BasicBlock * succBlock = BI->getSuccessor(index);
+ if (postDominates(currentBlock, succBlock)) {
+ DoneList.insert(CBB);
+ addControlDependentConditions(CBB,rootp);
+ addBranchConstraints(BI, BI->getSuccessor(index), rootp);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //adds constraints for known functions
+ ABCExprTree* ConstraintGeneration::addConstraintsForKnownFunctions(Function *kf, CallInst *CI) {
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedzero = ConstantInt::get(csiType,0);
+ string var = "0";
+ Constraint *c = new Constraint(var, new LinearExpr(signedzero, Mang),"=");
+ ABCExprTree *root = new ABCExprTree(c); //dummy constraint
+ ABCExprTree **rootp = &root;
+ string funcName = kf->getName();
+ if (funcName == "memcpy") {
+ string var = getValueName(CI->getOperand(1));
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(2),Mang);
+ Constraint *c1 = new Constraint(var,l1,">=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"||");
+ getConstraints(CI->getOperand(1), rootp);
+ getConstraints(CI->getOperand(2), rootp);
+ } else if (funcName == "llvm.memcpy") {
+ string var = getValueName(CI->getOperand(1));
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(2),Mang);
+ Constraint *c1 = new Constraint(var,l1,">=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"||");
+ getConstraints(CI->getOperand(1), rootp);
+ getConstraints(CI->getOperand(2), rootp);
+ } else if (funcName == "strlen") {
+ string var = getValueName(CI);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedzero = ConstantInt::get(csiType,0);
+
+ Constraint *c = new Constraint(var, new LinearExpr(signedzero, Mang),">=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(1),Mang);
+ Constraint *c1 = new Constraint(var,l1,"<");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ getConstraints(CI->getOperand(1), rootp);
+ } else if (funcName == "read") {
+ string var = getValueName(CI);
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(3),Mang);
+ Constraint *c1 = new Constraint(var,l1,"<=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ getConstraints(CI->getOperand(3), rootp);
+
+ } else if (funcName == "fread") {
+ string var = getValueName(CI);
+ LinearExpr *l1 = new LinearExpr(CI->getOperand(2),Mang);
+ LinearExpr *l2 = new LinearExpr(CI->getOperand(3),Mang);
+ l2->mulLinearExpr(l1);
+ Constraint *c1 = new Constraint(var,l2,"<=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ getConstraints(CI->getOperand(3), rootp);
+ getConstraints(CI->getOperand(2), rootp);
+
+ } else {
+ // out << funcName << " is not supported yet \n";
+ // Ignoring some functions is okay as long as they are not part of the
+ //one of the multiple indirect calls
+ assert((CI->getOperand(0) == kf) && "Need to handle this properly \n");
+ }
+ return root;
+ }
+
+
+ void ConstraintGeneration::getConstraints(Value *v, ABCExprTree **rootp) {
+ string tempName1 = getValueName(v);
+ LinearExpr *letemp1 = new LinearExpr(v,Mang);
+ Constraint* ctemp1 = new Constraint(tempName1,letemp1,"=");
+ ABCExprTree* abctemp1 = new ABCExprTree(ctemp1);
+ getConstraintsInternal(v,&abctemp1);
+ *rootp = new ABCExprTree(*rootp, abctemp1, "&&");
+ }
+
+ //Get Constraints on a value v, this assumes that the Table is correctly set
+ //for the function that is cal ling this
+ void ConstraintGeneration::getConstraintsInternal(Value *v, ABCExprTree **rootp) {
+ string var;
+ if ( Instruction *I = dyn_cast<Instruction>(v)) {
+
+ Function* func = I->getParent()->getParent();
+ BasicBlock * currentBlock = I->getParent();
+
+ //Here we need to add the post dominator stuff if necessary
+ addControlDependentConditions(currentBlock, rootp);
+
+ if (!isa<ReturnInst>(I)) {
+ var = getValueName(I);
+ } else {
+ var = getValueName(func);
+ }
+ if (fMap.count(func)) {
+ if (fMap[func]->inLocalConstraints(I)) { //checking the cache
+ if (fMap[func]->getLocalConstraint(I) != 0) {
+ *rootp = new ABCExprTree(*rootp, fMap[func]->getLocalConstraint(I),"&&");
+ }
+ return;
+ }
+ } else {
+ fMap[func] = new FuncLocalInfo();
+ }
+ fMap[func]->addLocalConstraint(I,0);
+ if (isa<SwitchInst>(I)) {
+ //TODO later
+ } else if (ReturnInst * ri = dyn_cast<ReturnInst>(I)) {
+ if (ri->getNumOperands() > 0) {
+ //For getting the constraints on return values
+ LinearExpr *l1 = new LinearExpr(ri->getOperand(0),Mang);
+ Constraint *c1 = new Constraint(var,l1,"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ getConstraints(ri->getOperand(0), rootp);
+ }
+
+ } else if (PHINode *p = dyn_cast<PHINode>(I)) {
+ //its a normal PhiNode
+ if (indMap.count(p) > 0) {
+ //We know that this is the canonical induction variable
+ //First get the upper bound
+ Value *UBound = indMap[p];
+ LinearExpr *l1 = new LinearExpr(UBound, Mang);
+ Constraint *c1 = new Constraint(var, l1, "<");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedzero = ConstantInt::get(csiType,0);
+ LinearExpr *l2 = new LinearExpr(signedzero, Mang);
+ Constraint *c2 = new Constraint(var, l2, ">=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c2),"&&");
+
+ getConstraints(UBound, rootp);
+
+ }
+ } else if (isa<CallInst>(I)) {
+ CallInst * CI = dyn_cast<CallInst>(I);
+ //First we have to check if it is an RMalloc
+ if (CI->getOperand(0)->getName() == "RMalloc") {
+ //It is an RMalloc, we knoe it has only one argument
+ Constraint *c = new Constraint(var, SimplifyExpression(I->getOperand(1),rootp),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ } else {
+ if (fMap.count(func) == 0) {
+ fMap[func] = new FuncLocalInfo();
+ }
+ //This also get constraints for arguments of CI
+ getConstraintsAtCallSite(CI, rootp);
+ }
+ }
+ else if (isa<AllocationInst>(I)) {
+ //Note that this is for the local variables which are converted in to
+ //allocas, mallocs , we take care of the RMallocs (CASES work)in the CallInst case
+ AllocationInst *AI = cast<AllocationInst>(I);
+ if (const ArrayType *AT = dyn_cast<ArrayType>(AI->getType()->getElementType())) {
+ //sometime allocas have some array as their allocating constant !!
+ //We then have to generate constraints for all the dimensions
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,1);
+
+ Constraint *c = new Constraint(var, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ generateArrayTypeConstraints(var, AT, rootp);
+ } else {
+ //This is the general case, where the allocas/mallocs are allocated by some
+ //variable
+ //Ugly hack because of the llvm front end's cast of
+ //argument of malloc to uint
+ fromMalloc = true;
+ Value *sizeVal = I->getOperand(0) ;
+ // if (CastInst *csI = dyn_cast<CastInst>(I->getOperand(0))) {
+ // const Type *toType = csI->getType();
+ // const Type *fromType = csI->getOperand(0)->getType();
+ // if ((toType->isPrimitiveType()) && (toType->getPrimitiveID() == Type::UIntTyID)) {
+ // sizeVal = csI->getOperand(0);
+ // }
+ // }
+ Constraint *c = new Constraint(var, SimplifyExpression(sizeVal,rootp),"=");
+ fromMalloc = false;
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ } else if (isa<GetElementPtrInst>(I)) {
+
+
+ GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
+ Value *PointerOperand = I->getOperand(0);
+ if (const PointerType *pType = dyn_cast<PointerType>(PointerOperand->getType()) ){
+ //this is for arrays inside structs
+ if (const StructType *stype = dyn_cast<StructType>(pType->getElementType())) {
+ //getelementptr *key, long 0, ubyte 0, long 18
+ if (GEP->getNumOperands() == 4) {
+ if (const ArrayType *aType = dyn_cast<ArrayType>(stype->getContainedType(0))) {
+ int elSize = aType->getNumElements();
+ if (const ConstantInt *CSI = dyn_cast<ConstantInt>(I->getOperand(3))) {
+ elSize = elSize - CSI->getSExtValue();
+ if (elSize == 0) {
+ //Dirty HACK, this doesnt work for more than 2 arrays in a struct!!
+ if (const ArrayType *aType2 = dyn_cast<ArrayType>(stype->getContainedType(1))) {
+ elSize = aType2->getNumElements();
+ }
+ }
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,elSize);
+ Constraint *c = new Constraint(var, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ }
+ }
+ }
+ }
+ //dunno if this is a special case or need to be generalized
+ //FIXME for now it is a special case.
+ if (I->getNumOperands() == 2) {
+ getConstraints(PointerOperand,rootp);
+ getConstraints(GEP->getOperand(1),rootp);
+ LinearExpr *L1 = new LinearExpr(GEP->getOperand(1), Mang);
+ LinearExpr *L2 = new LinearExpr(PointerOperand, Mang);
+ L1->negate();
+ L1->addLinearExpr(L2);
+ Constraint *c = new Constraint(var, L1,"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ //This is added for the special case found in the embedded bench marks
+ //Normally GetElementPtrInst is taken care by the getSafetyConstraints
+ //But sometimes you get a pointer to an array x = &x[0]
+ //z = getelementptr x 0 0
+ //getlelementptr z is equivalent to getelementptr x !
+ if (I->getNumOperands() == 3) {
+ if (const PointerType *PT = dyn_cast<PointerType>(PointerOperand->getType())) {
+ if (const ArrayType *AT = dyn_cast<ArrayType>(PT->getElementType())) {
+ if (const ConstantInt *CSI = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ if (CSI->getSExtValue() == 0) {
+ if (const ConstantInt *CSI2 = dyn_cast<ConstantInt>(I->getOperand(2))) {
+ if (CSI2->getSExtValue() == 0) {
+ //Now add the constraint
+
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,AT->getNumElements());
+ Constraint *c = new Constraint(var, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ Constraint *c = new Constraint(var, SimplifyExpression(I,rootp),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ fMap[func]->addLocalConstraint(I,*rootp); //storing in the cache
+ } else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(v)) {
+ //Its a global variable...
+ //It could be an array
+ var = getValueName(GV);
+ if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) {
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,1);
+
+ Constraint *c = new Constraint(var, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ generateArrayTypeConstraintsGlobal(var, AT, rootp, 1);
+ }
+ }
+ }
+
+ void ConstraintGeneration::generateArrayTypeConstraintsGlobal(string var, const ArrayType *T, ABCExprTree **rootp, unsigned int numElem) {
+ string var1 = var + "_i";
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ if (const ArrayType *AT = dyn_cast<ArrayType>(T->getElementType())) {
+ const ConstantInt * signedOne = ConstantInt::get(csiType,1);
+ Constraint *c = new Constraint(var1, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ generateArrayTypeConstraintsGlobal(var1,AT, rootp, T->getNumElements() * numElem);
+ } else {
+ const ConstantInt * signedOne = ConstantInt::get(csiType,numElem * T->getNumElements());
+ Constraint *c = new Constraint(var1, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ }
+
+
+ void ConstraintGeneration::generateArrayTypeConstraints(string var, const ArrayType *T, ABCExprTree **rootp) {
+ string var1 = var + "_i";
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,T->getNumElements());
+ Constraint *c = new Constraint(var1, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ if (const ArrayType *AT = dyn_cast<ArrayType>(T->getElementType())) {
+ generateArrayTypeConstraints(var1,AT, rootp);
+ } else if (const StructType *ST = dyn_cast<StructType>(T->getElementType())) {
+ //This will only work one level of arrays and structs
+ //If there are arrays inside a struct then this will
+ //not help us prove the safety of the access ....
+ unsigned Size = getAnalysis<TargetData>().getTypeSize(ST);
+ string var2 = var1 + "_i";
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,Size);
+ Constraint *c = new Constraint(var2, new LinearExpr(signedOne, Mang),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ }
+ }
+
+ABCExprTree *ConstraintGeneration::getArgumentConstraints(Function & F) {
+ if (buCG->isInSCC(&F)) return 0; //Ignore recursion for now
+ std::set<Function *> reqArgFList;
+ bool localSave = reqArgs;
+ //First check if it is in cache
+ ABCExprTree *root = fMap[&F]->getArgumentConstraints();
+ if (root) {
+ return root;
+ } else {
+ //Its not there in cache, so we compute it
+ if (buCG->FuncCallSiteMap.count(&F)) {
+ std::vector<CallSite> &cslist = buCG->FuncCallSiteMap[&F];
+ for (unsigned idx = 0, sz = cslist.size(); idx != sz; ++idx) {
+ ABCExprTree *rootCallInst = 0;
+ if (CallInst *CI = dyn_cast<CallInst>(cslist[idx].getInstruction())) {
+ //we need to AND the constraints on the arguments
+ reqArgs = false;
+ Function::arg_iterator formalArgCurrent = F.arg_begin(), formalArgEnd = F.arg_end();
+ for (unsigned i = 1; formalArgCurrent != formalArgEnd; ++formalArgCurrent, ++i) {
+ if (i < CI->getNumOperands()) {
+ string varName = getValueName(formalArgCurrent);
+ Value *OperandVal = CI->getOperand(i);
+ LinearExpr *le = new LinearExpr(OperandVal,Mang);
+ Constraint* c1 = new Constraint(varName,le,"=");
+ ABCExprTree *temp = new ABCExprTree(c1);
+ if (!isa<Constant>(OperandVal)) {
+ getConstraints(OperandVal,&temp);
+ }
+ if (!rootCallInst) {
+ rootCallInst = temp;
+ } else {
+ rootCallInst = new ABCExprTree(rootCallInst, temp, "&&");
+ }
+ }
+ }
+ if (reqArgs) {
+ //This Call site requires args better to maintain a set
+ //and get the argument constraints once for all
+ //since there could be multiple call sites from the same function
+ reqArgFList.insert(CI->getParent()->getParent());
+ }
+ }
+ if (!root) root = rootCallInst;
+ else {
+ root = new ABCExprTree(root, rootCallInst, "||");
+ }
+ }
+ std::set<Function *>::iterator sI = reqArgFList.begin(), sE= reqArgFList.end();
+ for (; sI != sE ; ++sI) {
+ ABCExprTree * argConstraints = getArgumentConstraints(**sI);
+ if (argConstraints) root = new ABCExprTree(root, argConstraints, "&&");
+ }
+ fMap[&F]->addArgumentConstraints(root); //store it in cache
+ }
+ }
+ reqArgs = localSave;
+ return root;
+ }
+
+
+bool ConstraintGeneration::runOnModule(Module &M) {
+ cbudsPass = &getAnalysis<CompleteBUDataStructures>();
+ buCG = &getAnalysis<BottomUpCallGraph>();
+ Mang = new Mangler(M);
+
+ initialize(M);
+ return false;
+}
+
+
+void ConstraintGeneration::addBranchConstraints(BranchInst *BI,BasicBlock *Successor, ABCExprTree **rootp) {
+ //this has to be a conditional branch, otherwise we wouldnt have been here
+ assert((BI->isConditional()) && "abcd wrong branch constraint");
+ if (SetCondInst *SCI = dyn_cast<SetCondInst>(BI->getCondition())) {
+
+ //SCI now has the conditional statement
+ Value *operand0 = SCI->getOperand(0);
+ Value *operand1 = SCI->getOperand(1);
+
+ getConstraints(operand0,rootp);
+ getConstraints(operand1,rootp);
+
+
+ LinearExpr *l1 = new LinearExpr(operand1,Mang);
+
+ string var0 = getValueName(operand0);
+ Constraint *ct = 0;
+
+ switch(SCI->getOpcode()) {
+ case Instruction::SetLE :
+ //there are 2 cases for each opcode!
+ //its the true branch or the false branch
+ if (BI->getSuccessor(0) == Successor) {
+ //true branch
+ ct = new Constraint(var0,l1,"<=");
+ } else {
+ ct = new Constraint(var0,l1,">");
+ }
+ break;
+ case Instruction::SetGE :
+ if (BI->getSuccessor(0) == Successor) {
+ //true branch
+ ct = new Constraint(var0,l1,">=");
+ } else {
+ //false branch
+ ct = new Constraint(var0,l1,"<");
+ }
+ break;
+ case Instruction::SetLT :
+ if (BI->getSuccessor(0) == Successor) {
+ //true branch
+ ct = new Constraint(var0,l1,"<");
+ } else {
+ //false branch
+ ct = new Constraint(var0,l1,">=");
+ }
+ break;
+ case Instruction::SetGT :
+ if (BI->getSuccessor(0) == Successor) {
+ //true branch
+ ct = new Constraint(var0,l1,">");
+ } else {
+ //false branch
+ ct = new Constraint(var0,l1,"<=");
+ }
+ break;
+ default :
+ break;
+ }
+ if (ct != 0) {
+ ct->print(std::cerr);
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(ct),"&&");
+ }
+ }
+}
+
+
+
+// SimplifyExpression: Simplify a Value and return it as an affine expressions
+LinearExpr* ConstraintGeneration::SimplifyExpression( Value *Expr, ABCExprTree **rootp) {
+ assert(Expr != 0 && "Can't classify a null expression!");
+ if (Expr->getType() == Type::FloatTy || Expr->getType() == Type::DoubleTy)
+ return new LinearExpr(Expr, Mang) ; // nothing known return variable itself
+
+ if ((isa<BasicBlock>(Expr)) || (isa<Function>(Expr)))
+ assert(1 && "Unexpected expression type to classify!");
+ if ((isa<GlobalVariable>(Expr)) || (isa<Argument>(Expr))) {
+ reqArgs = true; //I know using global is ugly, fix this later
+ return new LinearExpr(Expr, Mang);
+ }
+ if (isa<Constant>(Expr)) {
+ Constant *CPV = cast<Constant>(Expr);
+ if (CPV->getType()->isIntegral()) { // It's an integral constant!
+ if (dyn_cast<ConstantArray>(CPV)) {
+ assert(1 && "Constant Array don't know how to get the values ");
+ } else if (ConstantInt *CPI = dyn_cast<ConstantInt>(Expr)) {
+ return new LinearExpr(CPI, Mang);
+ }
+ }
+ return new LinearExpr(Expr, Mang); //nothing known, just return itself
+ }
+ if (isa<Instruction>(Expr)) {
+ Instruction *I = cast<Instruction>(Expr);
+
+ switch (I->getOpcode()) { // Handle each instruction type seperately
+ case Instruction::Add: {
+ LinearExpr* Left = (SimplifyExpression(I->getOperand(0), rootp));
+ if (Left == 0) {
+ Left = new LinearExpr(I->getOperand(0), Mang);
+ }
+ LinearExpr* Right = (SimplifyExpression(I->getOperand(1), rootp));
+ if (Right == 0) {
+ Right = new LinearExpr(I->getOperand(1), Mang);
+ }
+ Left->addLinearExpr(Right);
+ return Left;
+ }
+ case Instruction::Sub: {
+ LinearExpr* Left = (SimplifyExpression(I->getOperand(0), rootp));
+ if (Left == 0) {
+ Left = new LinearExpr(I->getOperand(0), Mang);
+ }
+ LinearExpr* Right = (SimplifyExpression(I->getOperand(1), rootp));
+ if (Right == 0) {
+ Right = new LinearExpr(I->getOperand(1), Mang);
+ }
+ Right->negate();
+ Left->addLinearExpr(Right);
+ return Left;
+ }
+ case Instruction::SetLE :
+ case Instruction::SetNE :
+ case Instruction::SetEQ :
+ case Instruction::SetGE :
+ case Instruction::SetLT :
+ case Instruction::SetGT : {
+ LinearExpr* L = new LinearExpr(I->getOperand(1),Mang);
+ return L;
+ };
+ case Instruction::Mul :
+
+ LinearExpr* Left = (SimplifyExpression(I->getOperand(0),rootp));
+ if (Left == 0) {
+ Left = new LinearExpr(I->getOperand(0), Mang);
+ }
+ LinearExpr* Right = (SimplifyExpression(I->getOperand(1),rootp));
+ if (Right == 0) {
+ Right = new LinearExpr(I->getOperand(1), Mang);
+ }
+ return Left->mulLinearExpr(Right);
+ } // end switch
+ if (isa<CastInst>(I)) {
+ DEBUG(std::cerr << "dealing with cast instruction ");
+ //Here we have to give constraints for
+ //FIXME .. this should be for all types not just sbyte
+ const Type *fromType = I->getOperand(0)->getType();
+ const Type *toType = I->getType();
+ string number1;
+ string number2;
+ bool addC = false;
+ if (toType->isPrimitiveType() && fromType->isPrimitiveType()) {
+ switch(toType->getTypeID()) {
+ case Type::IntTyID :
+ switch (fromType->getTypeID()) {
+ case Type::SByteTyID :
+ number1 = "-128";
+ number2 = "127";
+ addC = true;
+ break;
+ case Type::UByteTyID :
+ number1 = "0";
+ number2 = "255";
+ addC = true;
+ default:
+ break;
+ }
+ case Type::UIntTyID :
+ switch(fromType->getTypeID()) {
+ case Type::IntTyID :
+ //in llvm front end the malloc argument is always casted to
+ //uint! so we hack it here
+ //This hack works incorrectly for
+ //some programs so moved it to malloc itself
+ //FIXME FIXME This might give incorrect results in some cases!!!!
+ addC = true;
+ break;
+ case Type::SByteTyID :
+ case Type::UByteTyID :
+ number1 = "0";
+ number2 = "255";
+ addC = true;
+ break;
+ default :
+ break;
+ }
+ default:
+ break;
+ }
+ if (addC) {
+ string var = getValueName(I);
+ LinearExpr *l1 = new LinearExpr(I,Mang);
+ if (number1 != "") {
+ Constraint *c1 = new Constraint(number1,l1,">=",true);
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c1),"&&");
+ }
+ if (number2 != "") {
+ Constraint *c2 = new Constraint(number2,l1,"<=",true);
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c2),"&&");
+ }
+ Constraint *c = new Constraint(var, SimplifyExpression(I->getOperand(0),rootp),"=");
+ *rootp = new ABCExprTree(*rootp,new ABCExprTree(c),"&&");
+ return l1;
+ }
+ } else {
+ //special case for casts to beginning of structs
+ // the case is (sbyte*) (Struct with the first element arrauy)
+ //If it is a cast from struct to something else * ...
+ if (const PointerType *pType = dyn_cast<PointerType>(I->getType())){
+ const Type *eltype = pType->getElementType();
+ if (eltype->isPrimitiveType() && (eltype->getTypeID() == Type::SByteTyID)) {
+ if (const PointerType *opPType = dyn_cast<PointerType>(fromType)){
+ const Type *opEltype = opPType->getElementType();
+ if (const StructType *stype = dyn_cast<StructType>(opEltype)) {
+ if (const ArrayType *aType = dyn_cast<ArrayType>(stype->getContainedType(0))) {
+ if (aType->getElementType()->isPrimitiveType()) {
+ int elSize = aType->getNumElements();
+ switch (aType->getElementType()->getTypeID()) {
+ case Type::ShortTyID :
+ case Type::UShortTyID : elSize *= 2; break;
+ case Type::IntTyID :
+ case Type::UIntTyID : elSize *= 4; break;
+ case Type::LongTyID :
+ case Type::ULongTyID : elSize *= 8; break;
+ default : break;
+ }
+ string varName = getValueName(I);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ const ConstantInt * signedOne = ConstantInt::get(csiType,elSize);
+ LinearExpr *l1 = new LinearExpr(signedOne, Mang);
+ return l1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return SimplifyExpression(I->getOperand(0),rootp);
+ } else {
+ getConstraints(I,rootp);
+ LinearExpr* ret = new LinearExpr(I,Mang);
+ return ret;
+ }
+ }
+ // Otherwise, I don't know anything about this value!
+ return 0;
+}
+
+
+Pass *createConstraintGenerationPass() { return new ABC::ConstraintGeneration(); }
diff --git a/safecode/lib/ArrayBoundChecks/Makefile b/safecode/lib/ArrayBoundChecks/Makefile
new file mode 100755
index 0000000..cbc2178
--- /dev/null
+++ b/safecode/lib/ArrayBoundChecks/Makefile
@@ -0,0 +1,9 @@
+
+LEVEL = ../../
+
+DONT_BUILD_RELINKED=1
+SHARED_LIBRARY=1
+LIBRARYNAME=arrayboundcheck
+
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/lib/ConvertUnsafeAllocas/AllocaWithAggregateTypes.cpp b/safecode/lib/ConvertUnsafeAllocas/AllocaWithAggregateTypes.cpp
new file mode 100755
index 0000000..1ee5a14
--- /dev/null
+++ b/safecode/lib/ConvertUnsafeAllocas/AllocaWithAggregateTypes.cpp
@@ -0,0 +1,122 @@
+#include "llvm/Pass.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Type.h"
+#include "ConvertUnsafeAllocas.h"
+#include "llvm/Function.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Constants.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/VectorExtras.h"
+
+#include <iostream>
+
+using namespace llvm;
+
+namespace
+{
+
+ // Create the command line option for the pass
+ // RegisterOpt<MallocPass> X ("malloc", "Alloca to Malloc Pass");
+
+ inline bool MallocPass::TypeContainsPointer(const Type *Ty) {
+ if (Ty->getTypeID() == Type::PointerTyID)
+ return true;
+ else if (Ty->getTypeID() == Type::StructTyID) {
+ const StructType * structTy = cast<StructType>(Ty);
+ unsigned numE = structTy->getNumElements();
+ for (unsigned index = 0; index < numE; index++) {
+ if (TypeContainsPointer(structTy->getElementType(index)))
+ return true;
+ }
+ } else if (Ty->getTypeID() == Type::ArrayTyID) {
+ const ArrayType *arrayTy = cast<ArrayType>(Ty);
+ if (TypeContainsPointer(arrayTy->getElementType()))
+ return true;
+ }
+ return false;
+ }
+
+ inline bool
+ MallocPass::changeType (Instruction * Inst)
+ {
+ //
+ // Check to see if the instruction is an alloca.
+ //
+ if (Inst->getOpcode() == Instruction::Alloca) {
+ AllocationInst * AllocInst = cast<AllocationInst>(Inst);
+
+ //
+ // Get the type of object allocated.
+ //
+ const Type * TypeCreated = AllocInst->getAllocatedType ();
+
+ if (TypeContainsPointer(TypeCreated))
+ return true;
+
+ }
+ return false;
+ }
+
+ bool
+ MallocPass::runOnFunction (Function &F)
+ {
+ bool modified = false;
+ TargetData &TD = getAnalysis<TargetData>();
+ Module *theM = F.getParent();
+ Function *memsetF =
+ theM->getOrInsertFunction("memset", Type::VoidTy,
+ PointerType::get(Type::SByteTy), Type::IntTy ,
+ Type::UIntTy, 0);
+ for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
+ {
+ for (BasicBlock::iterator IAddrBegin=I->begin(), IAddrEnd = I->end();
+ IAddrBegin != IAddrEnd;
+ ++IAddrBegin)
+ {
+ //
+ // Determine if the instruction needs to be changed.
+ //
+ if (changeType (IAddrBegin))
+ {
+ AllocationInst * AllocInst = cast<AllocationInst>(IAddrBegin);
+ /*
+ //
+ // Get the type of object allocated.
+ //
+ const Type * TypeCreated = AllocInst->getAllocatedType ();
+
+ MallocInst * TheMalloc =
+ new MallocInst(TypeCreated, 0, AllocInst->getName(),
+ IAddrBegin);
+ std::cerr << "Found alloca that is struct or array" << std::endl;
+
+ //
+ // Remove old uses of the old instructions.
+ //
+ AllocInst->replaceAllUsesWith (TheMalloc);
+
+ //
+ // Remove the old instruction.
+ //
+ AllocInst->getParent()->getInstList().erase(AllocInst);
+ modified = true;
+ */
+
+ CastInst *CastI =
+ new CastInst(AllocInst,
+ PointerType::get(Type::SByteTy), "casted", AllocInst->getNext());
+ std::vector<Value *> args(1, CastI);
+ args.push_back(ConstantInt::get(Type::IntTy,204));
+ args.push_back(ConstantInt::get(Type::UIntTy,
+ TD.getTypeSize(AllocInst->getType())));
+ new CallInst(memsetF, args, "", CastI->getNext());
+ }
+ }
+ }
+ return modified;
+ }
+
+ RegisterPass<MallocPass> Z("convallocai", "converts unsafe allocas to mallocs");
+} // end of namespace
+
diff --git a/safecode/lib/ConvertUnsafeAllocas/Makefile b/safecode/lib/ConvertUnsafeAllocas/Makefile
new file mode 100755
index 0000000..e394742
--- /dev/null
+++ b/safecode/lib/ConvertUnsafeAllocas/Makefile
@@ -0,0 +1,9 @@
+
+LEVEL = ../../
+
+SHARED_LIBRARY=1
+DONT_BUILD_RELINKED=1
+LIBRARYNAME=convert
+
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/lib/ConvertUnsafeAllocas/convert.cpp b/safecode/lib/ConvertUnsafeAllocas/convert.cpp
new file mode 100755
index 0000000..67f320c
--- /dev/null
+++ b/safecode/lib/ConvertUnsafeAllocas/convert.cpp
@@ -0,0 +1,365 @@
+//===-- convert.cpp - EmbeC transformation that converts ------------//
+// unsafe allocas to mallocs
+// and updates the data structure analaysis accordingly
+// Needs abcpre abc and checkstack safety
+
+#include "safecode/Config/config.h"
+#include "ConvertUnsafeAllocas.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Instruction.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Analysis/Dominators.h"
+
+#include <iostream>
+
+using namespace llvm;
+using namespace CUA;
+using namespace ABC;
+
+extern DominatorSet::DomSetMapType dsmt;
+extern DominanceFrontier::DomSetMapType dfmt;
+
+static bool dominates(BasicBlock *bb1, BasicBlock *bb2) {
+ DominatorSet::DomSetMapType::const_iterator dsmtI = dsmt.find(bb1);
+ assert((dsmtI != dsmt.end()) && " basic block not found in dominator set");
+ return (dsmtI->second.count(bb2) != 0);
+}
+
+//
+// Statistics
+//
+static Statistic<> ConvAllocas ("convalloca", "Number of converted allocas");
+
+RegisterPass<ConvertUnsafeAllocas> cua("convalloca", "converts unsafe allocas");
+
+bool ConvertUnsafeAllocas::runOnModule(Module &M) {
+ //
+ // Retrieve all pre-requisite analysis results from other passes.
+ //
+ budsPass = &getAnalysis<CompleteBUDataStructures>();
+ cssPass = &getAnalysis<checkStackSafety>();
+ abcPass = &getAnalysis<ArrayBoundsCheck>();
+#if 0
+ tddsPass = &getAnalysis<TDDataStructures>();
+#endif
+ TD = &getAnalysis<TargetData>();
+#ifdef LLVA_KERNEL
+ //
+ // Get a reference to the kmalloc() function (the Linux kernel's general
+ // memory allocator function).
+ //
+ std::vector<const Type *> Arg(1, Type::UIntTy);
+ Arg.push_back(Type::IntTy);
+ FunctionType *kmallocTy = FunctionType::get(PointerType::get(Type::SByteTy), Arg, false);
+ kmalloc = M.getOrInsertFunction("kmalloc", kmallocTy);
+
+ //
+ // If we fail to get the kmalloc function, generate an error.
+ //
+ assert ((kmalloc != 0) && "No kmalloc function found!\n");
+#endif
+
+ unsafeAllocaNodes.clear();
+ getUnsafeAllocsFromABC();
+ // TransformCSSAllocasToMallocs(cssPass->AllocaNodes);
+ // TransformAllocasToMallocs(unsafeAllocaNodes);
+ // TransformCollapsedAllocas(M);
+ return true;
+}
+
+bool ConvertUnsafeAllocas::markReachableAllocas(DSNode *DSN) {
+ reachableAllocaNodes.clear();
+ return markReachableAllocasInt(DSN);
+}
+
+bool ConvertUnsafeAllocas::markReachableAllocasInt(DSNode *DSN) {
+ bool returnValue = false;
+ reachableAllocaNodes.insert(DSN);
+ if (DSN->isAllocaNode()) {
+ returnValue = true;
+ unsafeAllocaNodes.push_back(DSN);
+ }
+ for (unsigned i = 0, e = DSN->getSize(); i < e; i += DS::PointerSize)
+ if (DSNode *DSNchild = DSN->getLink(i).getNode()) {
+ if (reachableAllocaNodes.find(DSNchild) != reachableAllocaNodes.end()) {
+ continue;
+ } else if (markReachableAllocasInt(DSNchild)) {
+ returnValue = returnValue || true;
+ }
+ }
+ return returnValue;
+}
+
+void ConvertUnsafeAllocas::InsertFreesAtEnd(MallocInst *MI) {
+ //need to insert a corresponding free
+ // The dominator magic again
+ BasicBlock *currentBlock = MI->getParent();
+ DominanceFrontier::const_iterator it = dfmt.find(currentBlock);
+ if (it != dfmt.end()) {
+ const DominanceFrontier::DomSetType &S = it->second;
+ if (S.size() > 0) {
+ DominanceFrontier::DomSetType::iterator pCurrent = S.begin(), pEnd = S.end();
+ for (; pCurrent != pEnd; ++pCurrent) {
+ BasicBlock *frontierBlock = *pCurrent;
+ //One of its predecessors is dominated by
+ // currentBlock
+ //need to insert a free in that predecessor
+ for (pred_iterator SI = pred_begin(frontierBlock), SE = pred_end(frontierBlock);
+ SI != SE; ++SI) {
+ BasicBlock *predecessorBlock = *SI;
+ if (dominates(predecessorBlock, currentBlock)) {
+ //get the terminator
+ Instruction *InsertPt = predecessorBlock->getTerminator();
+ new FreeInst(MI, InsertPt);
+ }
+ }
+ }
+ }
+ } else {
+ //There is no dominance frontier, need to insert on all returns;
+ Function *F = MI->getParent()->getParent();
+ std::vector<Instruction*> FreePoints;
+ for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
+ if (isa<ReturnInst>(BB->getTerminator()) ||
+ isa<UnwindInst>(BB->getTerminator()))
+ FreePoints.push_back(BB->getTerminator());
+ //we have the Free points
+ //now we get
+ // Construct the free instructions at each of the points.
+ std::vector<Instruction*>::iterator fpI = FreePoints.begin(), fpE = FreePoints.end();
+ for (; fpI != fpE ; ++ fpI) {
+ Instruction *InsertPt = *fpI;
+ new FreeInst(MI, InsertPt);
+ }
+ }
+}
+
+// Precondition: Enforce that the alloca nodes haven't been already converted
+void ConvertUnsafeAllocas::TransformAllocasToMallocs(std::list<DSNode *>
+ & unsafeAllocaNodes) {
+
+ std::list<DSNode *>::const_iterator iCurrent = unsafeAllocaNodes.begin(),
+ iEnd = unsafeAllocaNodes.end();
+
+ for (; iCurrent != iEnd; ++iCurrent) {
+ DSNode *DSN = *iCurrent;
+
+ // Now change the alloca instruction corresponding to the node
+ // to malloc
+ DSGraph *DSG = DSN->getParentGraph();
+ DSGraph::ScalarMapTy &SM = DSG->getScalarMap();
+
+#ifndef LLVA_KERNEL
+ MallocInst *MI = 0;
+#else
+ CastInst *MI = 0;
+#endif
+ for (DSGraph::ScalarMapTy::iterator SMI = SM.begin(), SME = SM.end();
+ SMI != SME; ) {
+ bool stackAllocate = true;
+ // If this is already a heap node, then you cannot allocate this on the
+ // stack
+ if (DSN->isHeapNode()) {
+ stackAllocate = false;
+ }
+
+ if (SMI->second.getNode() == DSN) {
+ if (AllocaInst *AI = dyn_cast<AllocaInst>(SMI->first)) {
+ //create a new malloc instruction
+ if (AI->getParent() != 0) {
+#ifndef LLVA_KERNEL
+ MI = new MallocInst(AI->getType()->getElementType(),
+ AI->getArraySize(), AI->getName(), AI);
+#else
+ Value *AllocSize =
+ ConstantInt::get(Type::UIntTy,
+ TD->getTypeSize(AI->getAllocatedType()));
+
+ if (AI->isArrayAllocation())
+ AllocSize = BinaryOperator::create(Instruction::Mul, AllocSize,
+ AI->getOperand(0), "sizetmp",
+ AI);
+ std::vector<Value *> args(1, AllocSize);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ ConstantInt * signedzero = ConstantInt::get(csiType,32);
+ args.push_back(signedzero);
+ CallInst *CI = new CallInst(kmalloc, args, "", AI);
+ MI = new CastInst(CI, AI->getType(), "",AI);
+#endif
+ DSN->setHeapNodeMarker();
+ AI->replaceAllUsesWith(MI);
+ SM.erase(SMI++);
+ AI->getParent()->getInstList().erase(AI);
+ ++ConvAllocas;
+ // InsertFreesAtEnd(MI);
+#ifndef LLVA_KERNEL
+ if (stackAllocate) {
+ ArrayMallocs.insert(MI);
+ }
+#endif
+ } else {
+ ++SMI;
+ }
+ } else {
+ ++SMI;
+ }
+ } else {
+ ++SMI;
+ }
+ }
+ }
+}
+
+void ConvertUnsafeAllocas::TransformCSSAllocasToMallocs(std::vector<DSNode *> & cssAllocaNodes) {
+ std::vector<DSNode *>::const_iterator iCurrent = cssAllocaNodes.begin(),
+ iEnd = cssAllocaNodes.end();
+ for (; iCurrent != iEnd; ++iCurrent) {
+ DSNode *DSN = *iCurrent;
+
+ if (DSN->isNodeCompletelyFolded())
+ continue;
+
+ // If this is already listed in the unsafeAllocaNode vector, remove it
+ // since we are processing it here
+ std::list<DSNode *>::iterator NodeI = find(unsafeAllocaNodes.begin(),
+ unsafeAllocaNodes.end(),
+ DSN);
+ if (NodeI != unsafeAllocaNodes.end()) {
+ unsafeAllocaNodes.erase(NodeI);
+ }
+
+ // Now change the alloca instructions corresponding to this node to mallocs
+ DSGraph *DSG = DSN->getParentGraph();
+ DSGraph::ScalarMapTy &SM = DSG->getScalarMap();
+#ifndef LLVA_KERNEL
+ MallocInst *MI = 0;
+#else
+ CastInst *MI = 0;
+#endif
+ for (DSGraph::ScalarMapTy::iterator SMI = SM.begin(), SME = SM.end();
+ SMI != SME; ) {
+ if (SMI->second.getNode() == DSN) {
+ if (AllocaInst *AI = dyn_cast<AllocaInst>(SMI->first)) {
+ // Create a new malloc instruction
+ if (AI->getParent() != 0) { //This check for both stack and array
+#ifndef LLVA_KERNEL
+ MI = new MallocInst(AI->getType()->getElementType(),
+ AI->getArraySize(), AI->getName(), AI);
+ InsertFreesAtEnd(MI);
+#else
+ Value *AllocSize =
+ ConstantInt::get(Type::UIntTy,
+ TD->getTypeSize(AI->getAllocatedType()));
+
+ if (AI->isArrayAllocation())
+ AllocSize = BinaryOperator::create(Instruction::Mul, AllocSize,
+ AI->getOperand(0), "sizetmp",
+ AI);
+ std::vector<Value *> args(1, AllocSize);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ ConstantInt * signedzero = ConstantInt::get(csiType,32);
+ args.push_back(signedzero);
+ CallInst *CI = new CallInst(kmalloc, args, "", AI);
+ MI = new CastInst(CI, AI->getType(), "",AI);
+#endif
+ DSN->setHeapNodeMarker();
+ AI->replaceAllUsesWith(MI);
+ SM.erase(SMI++);
+ AI->getParent()->getInstList().erase(AI);
+ ++ConvAllocas;
+ } else {
+ ++SMI;
+ }
+ }else {
+ ++SMI;
+ }
+ }else {
+ ++SMI;
+ }
+ }
+ }
+}
+
+DSNode * ConvertUnsafeAllocas::getDSNode(const Value *V, Function *F) {
+ DSGraph &TDG = budsPass->getDSGraph(*F);
+ DSNode *DSN = TDG.getNodeForValue((Value *)V).getNode();
+ return DSN;
+}
+
+
+DSNode * ConvertUnsafeAllocas::getTDDSNode(const Value *V, Function *F) {
+#if 0
+ DSGraph &TDG = tddsPass->getDSGraph(*F);
+ DSNode *DSN = TDG.getNodeForValue((Value *)V).getNode();
+ return DSN;
+#else
+ return 0;
+#endif
+}
+
+void ConvertUnsafeAllocas::TransformCollapsedAllocas(Module &M) {
+ //Need to check if the following is incomplete becasue we are only looking at scalars.
+ //It may be complete because every instruction actually is a scalar in LLVM?!
+ for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
+ if (!MI->isExternal()) {
+ DSGraph &G = budsPass->getDSGraph(*MI);
+ DSGraph::ScalarMapTy &SM = G.getScalarMap();
+ for (DSGraph::ScalarMapTy::iterator SMI = SM.begin(), SME = SM.end();
+ SMI != SME; ) {
+ if (AllocaInst *AI = dyn_cast<AllocaInst>(SMI->first)) {
+ if (SMI->second.getNode()->isNodeCompletelyFolded()) {
+#ifndef LLVA_KERNEL
+ MallocInst *MI = new MallocInst(AI->getType()->getElementType(),
+ AI->getArraySize(), AI->getName(),
+ AI);
+#else
+ Value *AllocSize =
+ ConstantInt::get(Type::UIntTy,
+ TD->getTypeSize(AI->getAllocatedType()));
+ if (AI->isArrayAllocation())
+ AllocSize = BinaryOperator::create(Instruction::Mul, AllocSize,
+ AI->getOperand(0), "sizetmp",
+ AI);
+
+ std::vector<Value *> args(1, AllocSize);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ ConstantInt * signedzero = ConstantInt::get(csiType,32);
+ args.push_back(signedzero);
+ CallInst *CI = new CallInst(kmalloc, args, "", AI);
+ CastInst * MI = new CastInst(CI, AI->getType(), "",AI);
+#endif
+ AI->replaceAllUsesWith(MI);
+ SMI->second.getNode()->setHeapNodeMarker();
+ SM.erase(SMI++);
+ AI->getParent()->getInstList().erase(AI);
+ ++ConvAllocas;
+ } else {
+ ++SMI;
+ }
+ } else {
+ ++SMI;
+ }
+ }
+ }
+ }
+}
+
+void ConvertUnsafeAllocas::getUnsafeAllocsFromABC() {
+ std::vector<Instruction *> & UnsafeGetElemPtrs = abcPass->UnsafeGetElemPtrs;
+ std::vector<Instruction *>::const_iterator iCurrent = UnsafeGetElemPtrs.begin(), iEnd = UnsafeGetElemPtrs.end();
+ for (; iCurrent != iEnd; ++iCurrent) {
+ if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(*iCurrent)) {
+ Value *pointerOperand = GEP->getPointerOperand();
+ DSGraph &TDG = budsPass->getDSGraph(*(GEP->getParent()->getParent()));
+ DSNode *DSN = TDG.getNodeForValue(pointerOperand).getNode();
+ //FIXME DO we really need this ? markReachableAllocas(DSN);
+ if (DSN && DSN->isAllocaNode() && !DSN->isNodeCompletelyFolded()) {
+ unsafeAllocaNodes.push_back(DSN);
+ }
+ } else {
+
+ //call instruction add the corresponding *iCurrent->dump();
+ //FIXME abort();
+ }
+ }
+}
diff --git a/safecode/lib/InsertPoolChecks/Makefile b/safecode/lib/InsertPoolChecks/Makefile
new file mode 100755
index 0000000..788eac8
--- /dev/null
+++ b/safecode/lib/InsertPoolChecks/Makefile
@@ -0,0 +1,9 @@
+
+LEVEL = ../../
+
+SHARED_LIBRARY=1
+DONT_BUILD_RELINKED=1
+LIBRARYNAME=addchecks
+
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/lib/InsertPoolChecks/insert.cpp b/safecode/lib/InsertPoolChecks/insert.cpp
new file mode 100755
index 0000000..95c0ed1
--- /dev/null
+++ b/safecode/lib/InsertPoolChecks/insert.cpp
@@ -0,0 +1,869 @@
+#include "safecode/Config/config.h"
+#include "InsertPoolChecks.h"
+#include "llvm/Instruction.h"
+#include "llvm/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InstIterator.h"
+#include <iostream>
+#include "llvm/ADT/VectorExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+extern Value *getRepresentativeMetaPD(Value *);
+RegisterPass<InsertPoolChecks> ipc("safecode", "insert runtime checks");
+
+// Options for Enabling/Disabling the Insertion of Various Checks
+cl::opt<bool> EnableIncompleteChecks ("enable-incompletechecks", cl::Hidden,
+ cl::init(false),
+ cl::desc("Enable Checks on Incomplete Nodes"));
+
+cl::opt<bool> EnableNullChecks ("enable-nullchecks", cl::Hidden,
+ cl::init(false),
+ cl::desc("Enable Checks on NULL Pools"));
+
+
+cl::opt<bool> DisableLSChecks ("disable-lschecks", cl::Hidden,
+ cl::init(false),
+ cl::desc("Disable Load/Store Checks"));
+
+cl::opt<bool> DisableGEPChecks ("disable-gepchecks", cl::Hidden,
+ cl::init(false),
+ cl::desc("Disable GetElementPtr(GEP) Checks"));
+
+cl::opt<bool> DisableIntrinsicChecks ("disable-intrinchecks", cl::Hidden,
+ cl::init(false),
+ cl::desc("Disable Intrinsic Checks"));
+
+// Options for where to insert various initialization code
+cl::opt<string> InitFunctionName ("initfunc",
+ cl::desc("Specify name of initialization "
+ "function"),
+ cl::value_desc("function name"));
+
+// Pass Statistics
+static Statistic<> NullChecks ("safecode",
+ "Poolchecks with NULL pool descriptor");
+static Statistic<> FullChecks ("safecode",
+ "Poolchecks with non-NULL pool descriptor");
+static Statistic<> MissChecks ("safecode",
+ "Poolchecks omitted due to bad pool descriptor");
+static Statistic<> PoolChecks ("safecode", "Poolchecks Added");
+static Statistic<> BoundChecks("safecode",
+ "Bounds checks inserted");
+
+static Statistic<> MissedIncompleteChecks ("safecode",
+ "Poolchecks missed because of incompleteness");
+static Statistic<> MissedMultDimArrayChecks ("safecode",
+ "Multi-dimensional array checks");
+
+static Statistic<> MissedStackChecks ("safecode", "Missed stack checks");
+static Statistic<> MissedGlobalChecks ("safecode", "Missed global checks");
+static Statistic<> MissedNullChecks ("safecode", "Missed PD checks");
+
+bool InsertPoolChecks::runOnModule(Module &M) {
+ cuaPass = &getAnalysis<ConvertUnsafeAllocas>();
+ // budsPass = &getAnalysis<CompleteBUDataStructures>();
+#ifndef LLVA_KERNEL
+ paPass = &getAnalysis<PoolAllocate>();
+ equivPass = &(paPass->getECGraphs());
+ efPass = &getAnalysis<EmbeCFreeRemoval>();
+ TD = &getAnalysis<TargetData>();
+#else
+ TDPass = &getAnalysis<TDDataStructures>();
+#endif
+
+ //add the new poolcheck prototype
+ addPoolCheckProto(M);
+#ifndef LLVA_KERNEL
+ //register global arrays and collapsed nodes with global pools
+ registerGlobalArraysWithGlobalPools(M);
+#endif
+ //Replace old poolcheck with the new one
+ addPoolChecks(M);
+
+ //
+ // Update the statistics.
+ //
+ PoolChecks = NullChecks + FullChecks;
+
+ return true;
+}
+
+#ifndef LLVA_KERNEL
+void InsertPoolChecks::registerGlobalArraysWithGlobalPools(Module &M) {
+ Function *MainFunc = M.getMainFunction();
+ if (MainFunc == 0 || MainFunc->isExternal()) {
+ std::cerr << "Cannot do array bounds check for this program"
+ << "no 'main' function yet!\n";
+ abort();
+ }
+ //First register, argc and argv
+ Function::arg_iterator AI = MainFunc->arg_begin(), AE = MainFunc->arg_end();
+ if (AI != AE) {
+ //There is argc and argv
+ Value *Argc = AI;
+ AI++;
+ Value *Argv = AI;
+ PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*MainFunc);
+ Value *PH= getPoolHandle(Argv, MainFunc, *FI);
+ Function *PoolRegister = paPass->PoolRegister;
+ BasicBlock::iterator InsertPt = MainFunc->getEntryBlock().begin();
+ while ((isa<CallInst>(InsertPt)) || isa<CastInst>(InsertPt) || isa<AllocaInst>(InsertPt) || isa<BinaryOperator>(InsertPt)) ++InsertPt;
+ if (PH) {
+ Type *VoidPtrType = PointerType::get(Type::SByteTy);
+ Instruction *GVCasted = new CastInst(Argv,
+ VoidPtrType, Argv->getName()+"casted",InsertPt);
+ const Type* csiType = Type::getPrimitiveType(Type::UIntTyID);
+ Value *AllocSize = new CastInst(Argc,
+ csiType, Argc->getName()+"casted",InsertPt);
+ AllocSize = BinaryOperator::create(Instruction::Mul, AllocSize,
+ ConstantInt::get(csiType, 4), "sizetmp", InsertPt);
+ new CallInst(PoolRegister,
+ make_vector(PH, AllocSize, GVCasted, 0),
+ "", InsertPt);
+
+ } else {
+ std::cerr << "argv's pool descriptor is not present. \n";
+ // abort();
+ }
+
+ }
+ //Now iterate over globals and register all the arrays
+ Module::global_iterator GI = M.global_begin(), GE = M.global_end();
+ for ( ; GI != GE; ++GI) {
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GI)) {
+ Type *VoidPtrType = PointerType::get(Type::SByteTy);
+ Type *PoolDescType = ArrayType::get(VoidPtrType, 50);
+ Type *PoolDescPtrTy = PointerType::get(PoolDescType);
+ if (GV->getType() != PoolDescPtrTy) {
+ DSGraph &G = equivPass->getGlobalsGraph();
+ DSNode *DSN = G.getNodeForValue(GV).getNode();
+ if ((isa<ArrayType>(GV->getType()->getElementType())) || DSN->isNodeCompletelyFolded()) {
+ Value * AllocSize;
+ const Type* csiType = Type::getPrimitiveType(Type::UIntTyID);
+ if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) {
+ //std::cerr << "found global \n";
+ AllocSize = ConstantInt::get(csiType,
+ (AT->getNumElements() * TD->getTypeSize(AT->getElementType())));
+ } else {
+ AllocSize = ConstantInt::get(csiType, TD->getTypeSize(GV->getType()));
+ }
+ Function *PoolRegister = paPass->PoolRegister;
+ BasicBlock::iterator InsertPt = MainFunc->getEntryBlock().begin();
+ //skip the calls to poolinit
+ while ((isa<CallInst>(InsertPt)) || isa<CastInst>(InsertPt) || isa<AllocaInst>(InsertPt) || isa<BinaryOperator>(InsertPt)) ++InsertPt;
+
+ std::map<const DSNode *, Value *>::iterator I = paPass->GlobalNodes.find(DSN);
+ if (I != paPass->GlobalNodes.end()) {
+ Value *PH = I->second;
+ Instruction *GVCasted = new CastInst(GV,
+ VoidPtrType, GV->getName()+"casted",InsertPt);
+ new CallInst(PoolRegister,
+ make_vector(PH, AllocSize, GVCasted, 0),
+ "", InsertPt);
+ } else {
+ std::cerr << "pool descriptor not present \n ";
+ abort();
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
+void InsertPoolChecks::addPoolChecks(Module &M) {
+ if (!DisableGEPChecks) addGetElementPtrChecks(M);
+ if (!DisableLSChecks) addLoadStoreChecks(M);
+}
+
+
+#ifdef LLVA_KERNEL
+//
+// Method: addLSChecks()
+//
+// Description:
+// Insert a poolcheck() into the code for a load or store instruction.
+//
+void InsertPoolChecks::addLSChecks(Value *V, Instruction *I, Function *F) {
+ DSGraph & TDG = TDPass->getDSGraph(*F);
+ DSNode * Node = TDG.getNodeForValue(V).getNode();
+
+ if (Node && Node->isNodeCompletelyFolded()) {
+ if (!EnableIncompleteChecks) {
+ if (Node->isIncomplete()) {
+ ++MissedIncompleteChecks;
+ return;
+ }
+ }
+ // Get the pool handle associated with this pointer. If there is no pool
+ // handle, use a NULL pointer value and let the runtime deal with it.
+ Value *PH = getPoolHandle(V, F);
+#ifdef DEBUG
+std::cerr << "LLVA: addLSChecks: Pool " << PH << " Node " << Node << std::endl;
+#endif
+ // FIXME: We cannot handle checks to global or stack positions right now.
+ if ((!PH) || (Node->isAllocaNode()) || (Node->isGlobalNode())) {
+ ++NullChecks;
+ if (!PH) ++MissedNullChecks;
+ if (Node->isAllocaNode()) ++MissedStackChecks;
+ if (Node->isGlobalNode()) ++MissedGlobalChecks;
+
+ // Don't bother to insert the NULL check unless the user asked
+ if (!EnableNullChecks)
+ return;
+ PH = Constant::getNullValue(PointerType::get(Type::SByteTy));
+ } else {
+ //
+ // Only add the pool check if the pool is a global value or it
+ // belongs to the same basic block.
+ //
+ if (isa<GlobalValue>(PH)) {
+ ++FullChecks;
+ } else if (isa<Instruction>(PH)) {
+ Instruction * IPH = (Instruction *)(PH);
+ if (IPH->getParent() == I->getParent()) {
+ //
+ // If the instructions belong to the same basic block, ensure that
+ // the pool dominates the load/store.
+ //
+ Instruction * IP = IPH;
+ for (IP=IPH; (IP->isTerminator()) || (IP == I); IP=IP->getNext()) {
+ ;
+ }
+ if (IP == I)
+ ++FullChecks;
+ else {
+ ++MissChecks;
+ return;
+ }
+ } else {
+ ++MissChecks;
+ return;
+ }
+ } else {
+ ++MissChecks;
+ return;
+ }
+ }
+ // Create instructions to cast the checked pointer and the checked pool
+ // into sbyte pointers.
+ CastInst *CastVI =
+ new CastInst(V,
+ PointerType::get(Type::SByteTy), "node.lscasted", I);
+ CastInst *CastPHI =
+ new CastInst(PH,
+ PointerType::get(Type::SByteTy), "poolhandle.lscasted", I);
+
+ // Create the call to poolcheck
+ std::vector<Value *> args(1,CastPHI);
+ args.push_back(CastVI);
+ new CallInst(PoolCheck,args,"", I);
+ }
+}
+
+void InsertPoolChecks::addLoadStoreChecks(Module &M){
+ Module::iterator mI = M.begin(), mE = M.end();
+ for ( ; mI != mE; ++mI) {
+ Function *F = mI;
+ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+ if (LoadInst *LI = dyn_cast<LoadInst>(&*I)) {
+ Value *P = LI->getPointerOperand();
+ addLSChecks(P, LI, F);
+ } else if (StoreInst *SI = dyn_cast<StoreInst>(&*I)) {
+ Value *P = SI->getPointerOperand();
+ addLSChecks(P, SI, F);
+ }
+ }
+ }
+}
+#else
+
+void InsertPoolChecks::addLSChecks(Value *Vnew, const Value *V, Instruction *I, Function *F) {
+
+ PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F);
+ Value *PH = getPoolHandle(V, F, *FI );
+ DSNode* Node = getDSNode(V, F);
+ if (!PH) {
+ return;
+ } else {
+ if (PH && isa<ConstantPointerNull>(PH)) {
+ //we have a collapsed/Unknown pool
+ Value *PH = getPoolHandle(V, F, *FI, true);
+
+ if (dyn_cast<CallInst>(I)) {
+ // GEt the globals list corresponding to the node
+ return;
+ std::vector<Function *> FuncList;
+ Node->addFullFunctionList(FuncList);
+ std::vector<Function *>::iterator flI= FuncList.begin(), flE = FuncList.end();
+ unsigned num = FuncList.size();
+ if (flI != flE) {
+ const Type* csiType = Type::getPrimitiveType(Type::UIntTyID);
+ Value *NumArg = ConstantInt::get(csiType, num);
+
+ CastInst *CastVI =
+ new CastInst(Vnew,
+ PointerType::get(Type::SByteTy), "casted", I);
+
+ std::vector<Value *> args(1, NumArg);
+ args.push_back(CastVI);
+ for (; flI != flE ; ++flI) {
+ Function *func = *flI;
+ CastInst *CastfuncI =
+ new CastInst(func,
+ PointerType::get(Type::SByteTy), "casted", I);
+ args.push_back(CastfuncI);
+ }
+ new CallInst(FunctionCheck, args,"", I);
+ }
+ } else {
+
+
+ CastInst *CastVI =
+ new CastInst(Vnew,
+ PointerType::get(Type::SByteTy), "casted", I);
+ CastInst *CastPHI =
+ new CastInst(PH,
+ PointerType::get(Type::SByteTy), "casted", I);
+ std::vector<Value *> args(1,CastPHI);
+ args.push_back(CastVI);
+
+ new CallInst(PoolCheck,args,"", I);
+ }
+ }
+ }
+}
+
+
+void InsertPoolChecks::addLoadStoreChecks(Module &M){
+ Module::iterator mI = M.begin(), mE = M.end();
+ for ( ; mI != mE; ++mI) {
+ Function *F = mI;
+ //here we check that we only do this on original functions
+ //and not the cloned functions, the cloned functions may not have the
+ //DSG
+ bool isClonedFunc = false;
+ if (paPass->getFuncInfo(*F))
+ isClonedFunc = false;
+ else
+ isClonedFunc = true;
+ Function *Forig = F;
+ PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F);
+ if (isClonedFunc) {
+ Forig = paPass->getOrigFunctionFromClone(F);
+ }
+ //we got the original function
+
+ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+ if (LoadInst *LI = dyn_cast<LoadInst>(&*I)) {
+ //we need to get the LI from the original function
+ Value *P = LI->getPointerOperand();
+ if (isClonedFunc) {
+ assert(FI->NewToOldValueMap.count(LI) && " not in the value map \n");
+ const LoadInst *temp = dyn_cast<LoadInst>(FI->NewToOldValueMap[LI]);
+ assert(temp && " Instruction not there in the NewToOldValue map");
+ const Value *Ptr = temp->getPointerOperand();
+ addLSChecks(P, Ptr, LI, Forig);
+ } else {
+ addLSChecks(P, P, LI, Forig);
+ }
+ } else if (StoreInst *SI = dyn_cast<StoreInst>(&*I)) {
+ Value *P = SI->getPointerOperand();
+ if (isClonedFunc) {
+ assert(FI->NewToOldValueMap.count(SI) && " not in the value map \n");
+ const StoreInst *temp = dyn_cast<StoreInst>(FI->NewToOldValueMap[SI]);
+ assert(temp && " Instruction not there in the NewToOldValue map");
+ const Value *Ptr = temp->getPointerOperand();
+ addLSChecks(P, Ptr, SI, Forig);
+ } else {
+ addLSChecks(P, P, SI, Forig);
+ }
+ } else if (CallInst *CI = dyn_cast<CallInst>(&*I)) {
+ Value *FunctionOp = CI->getOperand(0);
+ if (!isa<Function>(FunctionOp)) {
+ if (isClonedFunc) {
+ assert(FI->NewToOldValueMap.count(CI) && " not in the value map \n");
+ const CallInst *temp = dyn_cast<CallInst>(FI->NewToOldValueMap[CI]);
+ assert(temp && " Instruction not there in the NewToOldValue map");
+ const Value* FunctionOp1 = temp->getOperand(0);
+ addLSChecks(FunctionOp, FunctionOp1, CI, Forig);
+ } else {
+ addLSChecks(FunctionOp, FunctionOp, CI, Forig);
+ }
+ }
+ }
+ }
+ }
+}
+
+#endif
+
+void InsertPoolChecks::addGetElementPtrChecks(Module &M) {
+ std::vector<Instruction *> & UnsafeGetElemPtrs = cuaPass->getUnsafeGetElementPtrsFromABC();
+ std::vector<Instruction *>::const_iterator iCurrent = UnsafeGetElemPtrs.begin(), iEnd = UnsafeGetElemPtrs.end();
+ for (; iCurrent != iEnd; ++iCurrent) {
+ // We have the GetElementPtr
+ if (!isa<GetElementPtrInst>(*iCurrent)) {
+ //Then this must be a function call
+ //FIXME, get strcpy and others from the backup dir and adjust them for LLVA
+ //Right now I just add memset &llva_memcpy for LLVA
+ // std::cerr << " function call \n";
+#ifdef LLVA_KERNEL
+ CallInst *CI = dyn_cast<CallInst>(*iCurrent);
+ if (CI && (!DisableIntrinsicChecks)) {
+ Value *Fop = CI->getOperand(0);
+ Function *F = CI->getParent()->getParent();
+ if (Fop->getName() == "llva_memcpy") {
+ Value *PH = getPoolHandle(CI->getOperand(1), F);
+ Instruction *InsertPt = CI;
+ if (!PH) {
+ ++NullChecks;
+ ++MissedNullChecks;
+
+ // Don't bother to insert the NULL check unless the user asked
+ if (!EnableNullChecks)
+ continue;
+ PH = Constant::getNullValue(PointerType::get(Type::SByteTy));
+ }
+ CastInst *CastCIUint =
+ new CastInst(CI->getOperand(1), Type::UIntTy, "node.lscasted", InsertPt);
+ CastInst *CastCIOp3 =
+ new CastInst(CI->getOperand(3), Type::UIntTy, "node.lscasted", InsertPt);
+ Instruction *Bop = BinaryOperator::create(Instruction::Add, CastCIUint,
+ CastCIOp3, "memcpyadd",InsertPt);
+
+ // Create instructions to cast the checked pointer and the checked pool
+ // into sbyte pointers.
+ CastInst *CastSourcePointer =
+ new CastInst(CI->getOperand(1),
+ PointerType::get(Type::SByteTy), "memcpy.1.casted", InsertPt);
+ CastInst *CastCI =
+ new CastInst(Bop,
+ PointerType::get(Type::SByteTy), "mempcy.2.casted", InsertPt);
+ CastInst *CastPHI =
+ new CastInst(PH,
+ PointerType::get(Type::SByteTy), "poolhandle.lscasted", InsertPt);
+
+ // Create the call to poolcheck
+ std::vector<Value *> args(1,CastPHI);
+ args.push_back(CastSourcePointer);
+ args.push_back(CastCI);
+ new CallInst(PoolCheckArray,args,"", InsertPt);
+#if 0
+ } else if (Fop->getName() == "memset") {
+ Value *PH = getPoolHandle(CI->getOperand(1), F);
+ Instruction *InsertPt = CI->getNext();
+ if (!PH) {
+ NullChecks++;
+ // Don't bother to insert the NULL check unless the user asked
+ if (!EnableNullChecks)
+ continue;
+ PH = Constant::getNullValue(PointerType::get(Type::SByteTy));
+ }
+ CastInst *CastCIUint =
+ new CastInst(CI, Type::UIntTy, "node.lscasted", InsertPt);
+ CastInst *CastCIOp3 =
+ new CastInst(CI->getOperand(3), Type::UIntTy, "node.lscasted", InsertPt);
+ Instruction *Bop = BinaryOperator::create(Instruction::Add, CastCIUint,
+ CastCIOp3, "memsetadd",InsertPt);
+
+ // Create instructions to cast the checked pointer and the checked pool
+ // into sbyte pointers.
+ CastInst *CastSourcePointer =
+ new CastInst(CI->getOperand(1),
+ PointerType::get(Type::SByteTy), "memset.1.casted", InsertPt);
+ CastInst *CastCI =
+ new CastInst(Bop,
+ PointerType::get(Type::SByteTy), "memset.2.casted", InsertPt);
+ CastInst *CastPHI =
+ new CastInst(PH,
+ PointerType::get(Type::SByteTy), "poolhandle.lscasted", InsertPt);
+
+ // Create the call to poolcheck
+ std::vector<Value *> args(1,CastPHI);
+ args.push_back(CastSourcePointer);
+ args.push_back(CastCI);
+ new CallInst(PoolCheckArray,args,"", InsertPt);
+#endif
+ }
+ }
+#endif
+ continue;
+ }
+ GetElementPtrInst *GEP = cast<GetElementPtrInst>(*iCurrent);
+ Function *F = GEP->getParent()->getParent();
+ // Now we need to decide if we need to pass in the alignmnet
+ //for the poolcheck
+ // if (getDSNodeOffset(GEP->getPointerOperand(), F)) {
+ // std::cerr << " we don't handle middle of structs yet\n";
+ //assert(!getDSNodeOffset(GEP->getPointerOperand(), F) && " we don't handle middle of structs yet\n");
+ // ++MissChecks;
+ // continue;
+ // }
+
+#ifndef LLVA_KERNEL
+ PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F);
+ Instruction *Casted = GEP;
+ if (!FI->ValueMap.empty()) {
+ assert(FI->ValueMap.count(GEP) && "Instruction not in the value map \n");
+ Instruction *temp = dyn_cast<Instruction>(FI->ValueMap[GEP]);
+ assert(temp && " Instruction not there in the Value map");
+ Casted = temp;
+ }
+ if (GetElementPtrInst *GEPNew = dyn_cast<GetElementPtrInst>(Casted)) {
+ Value *PH = getPoolHandle(GEP, F, *FI);
+ if (PH && isa<ConstantPointerNull>(PH)) continue;
+ if (!PH) {
+ Value *PointerOperand = GEPNew->getPointerOperand();
+ if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(PointerOperand)) {
+ if (cExpr->getOpcode() == Instruction::Cast)
+ PointerOperand = cExpr->getOperand(0);
+ }
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(PointerOperand)) {
+ if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) {
+ // We need to insert an actual check. It could be a select
+ // instruction.
+ // First get the size.
+ // This only works for one or two dimensional arrays.
+ if (GEPNew->getNumOperands() == 2) {
+ Value *secOp = GEPNew->getOperand(1);
+ if (secOp->getType() != Type::UIntTy) {
+ secOp = new CastInst(secOp, Type::UIntTy,
+ secOp->getName()+".ec.casted", Casted);
+ }
+
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ std::vector<Value *> args(1,secOp);
+ args.push_back(ConstantInt::get(csiType,AT->getNumElements()));
+ new CallInst(ExactCheck,args,"", Casted);
+ DEBUG(std::cerr << "Inserted exact check call Instruction \n");
+ continue;
+ } else if (GEPNew->getNumOperands() == 3) {
+ if (ConstantInt *COP = dyn_cast<ConstantInt>(GEPNew->getOperand(1))) {
+ // FIXME: assuming that the first array index is 0
+ assert((COP->getZExtValue() == 0) && "non zero array index\n");
+ Value * secOp = GEPNew->getOperand(2);
+ if (secOp->getType() != Type::UIntTy) {
+ secOp = new CastInst(secOp, Type::UIntTy,
+ secOp->getName()+".ec2.casted", Casted);
+ }
+ std::vector<Value *> args(1,secOp);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ args.push_back(ConstantInt::get(csiType,AT->getNumElements()));
+ new CallInst(ExactCheck, args, "", Casted->getNext());
+ continue;
+ } else {
+ // Handle non constant index two dimensional arrays later
+ abort();
+ }
+ } else {
+ // Handle Multi dimensional cases later
+ DEBUG(std::cerr << "WARNING: Handle multi dimensional globals later\n");
+ (*iCurrent)->dump();
+ }
+ }
+ DEBUG(std::cerr << " Global variable ok \n");
+ }
+
+ // These must be real unknowns and they will be handled anyway
+ // std::cerr << " WARNING, DID NOT HANDLE \n";
+ // (*iCurrent)->dump();
+ continue ;
+ } else {
+ if (Casted->getType() != PointerType::get(Type::SByteTy)) {
+ Casted = new CastInst(Casted,PointerType::get(Type::SByteTy),
+ (Casted)->getName()+".pc.casted",
+ (Casted)->getNext());
+ }
+ std::vector<Value *> args(1, PH);
+ args.push_back(Casted);
+ // Insert it
+ new CallInst(PoolCheck,args, "",Casted->getNext());
+ DEBUG(std::cerr << "inserted instrcution \n");
+ }
+ }
+#else
+ //
+ // Get the pool handle associated with the pointer operand.
+ //
+ Value *PH = getPoolHandle(GEP->getPointerOperand(), F);
+ GetElementPtrInst *GEPNew = GEP;
+ Instruction *Casted = GEP;
+
+ DSGraph & TDG = TDPass->getDSGraph(*F);
+ DSNode * Node = TDG.getNodeForValue(GEP).getNode();
+
+ DEBUG(std::cerr << "LLVA: addGEPChecks: Pool " << PH << " Node ");
+ DEBUG(std::cerr << Node << std::endl);
+
+ Value *PointerOperand = GEPNew->getPointerOperand();
+ if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(PointerOperand)) {
+ if (cExpr->getOpcode() == Instruction::Cast)
+ PointerOperand = cExpr->getOperand(0);
+ }
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(PointerOperand)) {
+ if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) {
+ // we need to insert an actual check
+ // It could be a select instruction
+ // First get the size
+ // This only works for one or two dimensional arrays
+ if (GEPNew->getNumOperands() == 2) {
+ Value *secOp = GEPNew->getOperand(1);
+ if (secOp->getType() != Type::UIntTy) {
+ secOp = new CastInst(secOp, Type::UIntTy,
+ secOp->getName()+".ec3.casted", Casted);
+ }
+
+ std::vector<Value *> args(1,secOp);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ args.push_back(ConstantInt::get(csiType,AT->getNumElements()));
+ CallInst *newCI = new CallInst(ExactCheck,args,"", Casted);
+ ++BoundChecks;
+ // DEBUG(std::cerr << "Inserted exact check call Instruction \n");
+ continue;
+ } else if (GEPNew->getNumOperands() == 3) {
+ if (ConstantInt *COP = dyn_cast<ConstantInt>(GEPNew->getOperand(1))) {
+ //FIXME assuming that the first array index is 0
+ assert((COP->getZExtValue() == 0) && "non zero array index\n");
+ Value * secOp = GEPNew->getOperand(2);
+ if (secOp->getType() != Type::UIntTy) {
+ secOp = new CastInst(secOp, Type::UIntTy,
+ secOp->getName()+".ec4.casted", Casted);
+ }
+ std::vector<Value *> args(1,secOp);
+ const Type* csiType = Type::getPrimitiveType(Type::IntTyID);
+ args.push_back(ConstantInt::get(csiType,AT->getNumElements()));
+ CallInst *newCI = new CallInst(ExactCheck,args,"", Casted->getNext());
+ ++BoundChecks;
+ continue;
+ } else {
+ //Handle non constant index two dimensional arrays later
+ abort();
+ }
+ } else {
+ //Handle Multi dimensional cases later
+ std::cerr << "WARNING: Handle multi dimensional globals later\n";
+ (*iCurrent)->dump();
+ ++MissedMultDimArrayChecks;
+ }
+ DEBUG(std::cerr << " Global variable ok \n");
+ }
+ }
+
+#if 0
+ //No checks for incomplete nodes
+ if (!EnableIncompleteChecks) {
+ if (Node->isIncomplete()) {
+ ++MissedNullChecks;
+ continue;
+ }
+ }
+#endif
+
+ //
+ // We cannot insert an exactcheck(). Insert a pool check.
+ //
+ // FIXME:
+ // Currently, we cannot register stack or global memory with pools. If
+ // the node is from alloc() or is a global, do not insert a poolcheck.
+ //
+#if 0
+ if ((!PH) || (Node->isAllocaNode()) || (Node->isGlobalNode())) {
+#else
+ if (!PH) {
+#endif
+ ++NullChecks;
+ if (!PH) ++MissedNullChecks;
+#if 0
+ if (Node->isAllocaNode()) ++MissedStackChecks;
+ if (Node->isGlobalNode()) ++MissedGlobalChecks;
+#endif
+ // Don't bother to insert the NULL check unless the user asked
+ if (!EnableNullChecks)
+ continue;
+ PH = Constant::getNullValue(PointerType::get(Type::SByteTy));
+ DEBUG(std::cerr << "missing a GEP check for" << GEP << "alloca case?\n");
+ } else {
+ //
+ // Determine whether the pool handle dominates the pool check.
+ // If not, then don't insert it.
+ //
+
+ //
+ // FIXME:
+ // This domination check is too restrictive; it eliminates pools that do
+ // dominate but are outside of the current basic block.
+ //
+ // Only add the pool check if the pool is a global value or it belongs
+ // to the same basic block.
+ //
+ if (isa<GlobalValue>(PH)) {
+ ++FullChecks;
+ } else if (isa<Instruction>(PH)) {
+ Instruction * IPH = (Instruction *)(PH);
+ if (IPH->getParent() == Casted->getParent()) {
+ //
+ // If the instructions belong to the same basic block, ensure that
+ // the pool dominates the load/store.
+ //
+ Instruction * IP = IPH;
+ for (IP=IPH; (IP->isTerminator()) || (IP==Casted); IP=IP->getNext()) {
+ ;
+ }
+ if (IP == Casted)
+ ++FullChecks;
+ else {
+ ++MissChecks;
+ continue;
+ }
+ } else {
+ ++MissChecks;
+ continue;
+ }
+ } else {
+ ++MissChecks;
+ continue;
+ }
+ }
+
+ //
+ // If this is a complete node, insert a poolcheck.
+ // If this is an icomplete node, insert a poolcheckarray.
+ //
+ Instruction *InsertPt = Casted->getNext();
+ if (Casted->getType() != PointerType::get(Type::SByteTy)) {
+ Casted = new CastInst(Casted,PointerType::get(Type::SByteTy),
+ (Casted)->getName()+".pc2.casted",InsertPt);
+ }
+ Instruction *CastedPointerOperand = new CastInst(PointerOperand,
+ PointerType::get(Type::SByteTy),
+ PointerOperand->getName()+".casted",InsertPt);
+ Instruction *CastedPH = new CastInst(PH,
+ PointerType::get(Type::SByteTy),
+ "ph",InsertPt);
+ if (Node->isIncomplete()) {
+ std::vector<Value *> args(1, CastedPH);
+ args.push_back(CastedPointerOperand);
+ args.push_back(Casted);
+ CallInst * newCI = new CallInst(PoolCheckArray,args, "",InsertPt);
+ } else {
+ std::vector<Value *> args(1, CastedPH);
+ args.push_back(Casted);
+ CallInst * newCI = new CallInst(PoolCheck,args, "",InsertPt);
+ }
+#endif
+ }
+}
+
+void InsertPoolChecks::addPoolCheckProto(Module &M) {
+ const Type * VoidPtrType = PointerType::get(Type::SByteTy);
+ /*
+ const Type *PoolDescType = ArrayType::get(VoidPtrType, 50);
+ // StructType::get(make_vector<const Type*>(VoidPtrType, VoidPtrType,
+ // Type::UIntTy, Type::UIntTy, 0));
+ const Type * PoolDescTypePtr = PointerType::get(PoolDescType);
+ */
+
+ std::vector<const Type *> Arg(1, VoidPtrType);
+ Arg.push_back(VoidPtrType);
+ FunctionType *PoolCheckTy =
+ FunctionType::get(Type::VoidTy,Arg, false);
+ PoolCheck = M.getOrInsertFunction("poolcheck", PoolCheckTy);
+
+ std::vector<const Type *> Arg2(1, VoidPtrType);
+ Arg2.push_back(VoidPtrType);
+ Arg2.push_back(VoidPtrType);
+ FunctionType *PoolCheckArrayTy =
+ FunctionType::get(Type::VoidTy,Arg2, false);
+ PoolCheckArray = M.getOrInsertFunction("poolcheckarray", PoolCheckArrayTy);
+
+ std::vector<const Type *> FArg2(1, Type::UIntTy);
+ FArg2.push_back(Type::IntTy);
+ FunctionType *ExactCheckTy = FunctionType::get(Type::VoidTy, FArg2, false);
+ ExactCheck = M.getOrInsertFunction("exactcheck", ExactCheckTy);
+
+ std::vector<const Type *> FArg3(1, Type::UIntTy);
+ FArg3.push_back(VoidPtrType);
+ FArg3.push_back(VoidPtrType);
+ FunctionType *FunctionCheckTy = FunctionType::get(Type::VoidTy, FArg3, true);
+ FunctionCheck = M.getOrInsertFunction("funccheck", FunctionCheckTy);
+
+}
+
+DSNode* InsertPoolChecks::getDSNode(const Value *V, Function *F) {
+#ifndef LLVA_KERNEL
+ DSGraph &TDG = equivPass->getDSGraph(*F);
+#else
+ DSGraph &TDG = TDPass->getDSGraph(*F);
+#endif
+ DSNode *DSN = TDG.getNodeForValue((Value *)V).getNode();
+ return DSN;
+}
+
+unsigned InsertPoolChecks::getDSNodeOffset(const Value *V, Function *F) {
+#ifndef LLVA_KERNEL
+ DSGraph &TDG = equivPass->getDSGraph(*F);
+#else
+ DSGraph &TDG = TDPass->getDSGraph(*F);
+#endif
+ return TDG.getNodeForValue((Value *)V).getOffset();
+}
+#ifndef LLVA_KERNEL
+Value *InsertPoolChecks::getPoolHandle(const Value *V, Function *F, PA::FuncInfo &FI, bool collapsed) {
+ const DSNode *Node = getDSNode(V,F);
+ // Get the pool handle for this DSNode...
+ // assert(!Node->isUnknownNode() && "Unknown node \n");
+ Type *VoidPtrType = PointerType::get(Type::SByteTy);
+ Type *PoolDescType = ArrayType::get(VoidPtrType, 50);
+ Type *PoolDescPtrTy = PointerType::get(PoolDescType);
+ if (!Node) {
+ return 0; //0 means there is no isse with the value, otherwise there will be a callnode
+ }
+ if (Node->isUnknownNode()) {
+ //FIXME this should be in a top down pass or propagated like collapsed pools below
+ if (!collapsed) {
+ assert(!getDSNodeOffset(V, F) && " we don't handle middle of structs yet\n");
+ return Constant::getNullValue(PoolDescPtrTy);
+ }
+ }
+ std::map<const DSNode*, Value*>::iterator I = FI.PoolDescriptors.find(Node);
+ map <Function *, set<Value *> > &
+ CollapsedPoolPtrs = efPass->CollapsedPoolPtrs;
+
+ if (I != FI.PoolDescriptors.end()) {
+ // Check that the node pointed to by V in the TD DS graph is not
+ // collapsed
+
+ if (!collapsed && CollapsedPoolPtrs.count(F)) {
+ Value *v = I->second;
+ if (CollapsedPoolPtrs[F].find(I->second) !=
+ CollapsedPoolPtrs[F].end()) {
+#ifdef DEBUG
+ std::cerr << "Collapsed pools \n";
+#endif
+ return Constant::getNullValue(PoolDescPtrTy);
+ } else {
+ return v;
+ }
+ } else {
+ return I->second;
+ }
+ }
+ return 0;
+}
+#else
+Value *InsertPoolChecks::getPoolHandle(const Value *V, Function *F) {
+ DSGraph &TDG = TDPass->getDSGraph(*F);
+ const DSNode *Node = TDG.getNodeForValue((Value *)V).getNode();
+ // Get the pool handle for this DSNode...
+ // assert(!Node->isUnknownNode() && "Unknown node \n");
+ // if (Node->isUnknownNode()) {
+ // return 0;
+ // }
+ if ((TDG.getPoolDescriptorsMap()).count(Node))
+ return (TDG.getPoolDescriptorsMap()[Node]->getMetaPoolValue());
+ return 0;
+}
+#endif
diff --git a/safecode/lib/Makefile b/safecode/lib/Makefile
new file mode 100755
index 0000000..159129f
--- /dev/null
+++ b/safecode/lib/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ..
+
+PARALLEL_DIRS = ArrayBoundChecks ConvertUnsafeAllocas InsertPoolChecks StackSafety PointerChecks
+
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/lib/PointerChecks/CZero.cpp b/safecode/lib/PointerChecks/CZero.cpp
new file mode 100755
index 0000000..daa0ec9
--- /dev/null
+++ b/safecode/lib/PointerChecks/CZero.cpp
@@ -0,0 +1,464 @@
+//===-- CZero.cpp - CZero security checks ----------------===//
+//
+// This transformation ensures that the code emitted (if there are no warnings)
+// poses no security threat to the target system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/IPO.h"
+#include "CZeroInfo.h"
+#include "llvm/Module.h"
+#include "llvm/Argument.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/Function.h"
+#include "llvm/Support/CFG.h"
+#include <iostream>
+using namespace llvm;
+
+
+//===----------------------------------------------------------------------===//
+// CZeroInfo Implementation
+//===----------------------------------------------------------------------===//
+
+string CZeroInfo::WarningString(enum WarningType WT) {
+ switch (WT) {
+ case NoWarning: return "";
+ case IllegalMemoryLoc: return "Accessing an illegal memory location\n";
+ case UninitPointer: return "Potential use of location pointed to by uninitialized pointer variable\n";
+ default: return "";
+ }
+}
+
+string& CZeroInfo::getWarnings() {
+
+ // Lazy evaluation.
+ // TODO: Introduce an analyzed bool flag so that we
+ // don't end up redo-ing the evaluation when there are no security warnings
+ if (WarningsList != "")
+ return WarningsList;
+
+ // Uninitialized pointers
+ depthFirstGatherer();
+
+ findSpuriousInsts();
+
+ return WarningsList;
+
+}
+
+void CZeroInfo::depthFirstGatherer() {
+ // Adding the pointer values among the arguments to the alias graph
+ // We treat them as pointers to global targets.
+
+ for (Function::const_arg_iterator I = TheFunction.arg_begin(),
+ E = TheFunction.arg_end(); I != E; ++I) {
+ if (I->getType()->getTypeID() == Type::PointerTyID)
+ PointerAliasGraph.addEdge(I, PointsToTarget::GlobalTarget);
+ }
+
+ df_iterator<const Function*> It = df_begin(&TheFunction), End = df_end(&TheFunction);
+ for ( ; It != End; It++) {
+ const BasicBlock *BB = *It;
+
+ // Look for store instructions sequentially in the basic block
+ // updating pointer alias graphs for the other instructions
+ BasicBlock::const_iterator iterBB;
+ for (iterBB = BB->begin(); iterBB != BB->end(); ++iterBB) {
+ const Instruction& I = *iterBB;
+
+ // NOTE!!! Removed the if (I) clause here
+ //
+ if (I.hasName() &&
+ I.getType()->getTypeID() == Type::PointerTyID) {
+ // Each of these cases needs to modify the alias graph appropriately
+ if (isa<AllocaInst>(I)) {
+ PointerAliasGraph.addEdge(&I, &I);
+ }
+ else if (isa<MallocInst>(I)) {
+ // TODO: We'll be making this illegal and only allowing
+ // calls to rmalloc and rfree.
+ PointerAliasGraph.addEdge(&I, &I);
+ }
+ else if (isa<LoadInst>(I)) {
+ PointerAliasGraph.addEdge(&I, PointsToTarget::DummyTarget);
+ }
+ else if (isa<GetElementPtrInst>(I)) {
+ // Check if the operand is a global value, in which case we
+ // generate an alias to a generic global value.
+ if (!isa<ConstantPointerNull>(I.getOperand(0)))
+ if (isa<GlobalValue>(I.getOperand(0)) ||
+ isa<Constant>(I.getOperand(0)))
+ PointerAliasGraph.addEdge(&I, PointsToTarget::GlobalTarget);
+ else
+ PointerAliasGraph.addAlias(&I, I.getOperand(0));
+ else
+ PointerAliasGraph.addEdge(&I, PointsToTarget::DummyTarget);
+ }
+ else if (isa<PHINode>(I)) {
+ PointerAliasGraph.addEdge(&I, &I);
+ }
+ else if (isa<CallInst>(I)) {
+ PointerAliasGraph.addEdge(&I, PointsToTarget::GlobalTarget);
+ }
+ else if (isa<CastInst>(I)) {
+ PointerAliasGraph.addEdge(&I, PointsToTarget::DummyTarget);
+ }
+ }
+ else if (!I.hasName()) {
+ if (isa<StoreInst>(I)) {
+ // We only consider stores of scalar pointers.
+ if (I.getNumOperands() <= 2 ||
+ (I.getNumOperands() == 3 &&
+ I.getOperand(2) != ConstantInt::get(Type::UIntTy, 0))) {
+ if (!isa<ConstantPointerNull>(I.getOperand(1))) {
+ BBPointerLiveInfo[BB][I.getOperand(1)] = true;
+ df_iterator<const Function*> localIt = df_begin(&TheFunction),
+ localEnd = df_end(&TheFunction);
+ for ( ; localIt != localEnd; ++localIt) {
+ if (DomSet->dominates((BasicBlock *) BB,
+ (BasicBlock *) *localIt))
+ BBPointerLiveInfo[*localIt][I.getOperand(1)] = true;
+ }
+ } else {
+ WarningsList += "Stores to null pointers disallowed in CZero\n";
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+bool CZeroInfo::checkPredecessors(const BasicBlock *BB, const Value *V,
+ set<const BasicBlock *>& visitedBlocks) {
+ set<const Value *> aliases = PointerAliasGraph.getAliases(V);
+ set<const Value *>::iterator Siter;
+
+ // Check the block BB itself. Necessary when checkPredecessors is called
+ // for a PHINode pointer
+ for (Siter = aliases.begin(); Siter != aliases.end(); ++Siter)
+ if (BBPointerLiveInfo[BB][*Siter])
+ return true;
+
+ pred_const_iterator PI = pred_begin(BB), PEnd = pred_end(BB);
+
+ if (PI != PEnd) {
+ for (; PI != PEnd; ++PI) {
+ if (visitedBlocks.find(*PI) == visitedBlocks.end()) {
+ bool alivehere = false;
+ visitedBlocks.insert(*PI);
+ for (Siter = aliases.begin(); Siter != aliases.end(); ++Siter)
+ if (BBPointerLiveInfo[*PI][*Siter])
+ alivehere = true;
+ if (!alivehere) {
+ if (!checkPredecessors(*PI, V, visitedBlocks))
+ return false;
+ else {
+ // Caching the value for future use.
+ for (Siter = aliases.begin(); Siter != aliases.end(); Siter++)
+ BBPointerLiveInfo[*PI][*Siter] = true;
+ }
+ }
+ }
+ }
+ }
+ else
+ return false;
+ return true;
+}
+
+// if BigSet contains even one of the elements in the smallset, return true
+// else return false
+static bool setContains (set<const Value *> BigSet, set<const Value *> SmallSet) {
+ set<const Value *>::iterator Siter;
+ bool found = false;
+ if (!SmallSet.empty())
+ for (Siter = SmallSet.begin(); Siter != SmallSet.end() && !found; Siter++)
+ if (BigSet.find(*Siter) != BigSet.end())
+ found = true;
+ return found;
+}
+
+// Called on PointerVar only if PointerVar is a scalar, non-heap variable.
+// However the case that PointerVar points to a phi node needs to be handled.
+enum WarningType CZeroInfo::checkIfStored(const BasicBlock *BB,
+ const Value *PointerVar,
+ std::set<const Value *>&
+ LocalStoresSoFar) {
+ if (!isa<ConstantPointerNull>(PointerVar))
+ return NoWarning;
+ // TODO: Optimization if a pointer is defined in the same basic block.
+ set<const Value *> aliases = PointerAliasGraph.getAliases(PointerVar);
+ set<const BasicBlock *> visitedBlocks;
+ visitedBlocks.insert(BB);
+ if (PointerAliasGraph.getPointsToInfo(PointerVar).isPHINode()) {
+ // We have a phi node pointer
+ // Solve separate problems for each of the predecessors
+ if (!setContains(LocalStoresSoFar, aliases)) {
+ // Each of the predecessor branches.
+ bool stored = true;
+ const PHINode *pI = dyn_cast<const PHINode>(PointerAliasGraph.getPointsToInfo(PointerVar).val());
+ // There has to be at least one predecessor
+ for (unsigned int i = 0; i < pI->getNumIncomingValues(); i++) {
+ if (!checkPredecessors(pI->getIncomingBlock(i),
+ pI->getIncomingValue(i),
+ visitedBlocks))
+ stored = false;
+ }
+ if (!stored)
+ return UninitPointer;
+ else {
+ // Cache the value
+ set<const Value *>::iterator Siter;
+ for (Siter = aliases.begin(); Siter != aliases.end(); Siter++)
+ BBPointerLiveInfo[BB][*Siter] = true;
+ }
+ }
+ }
+ else {
+ if (!setContains(LocalStoresSoFar, aliases))
+ if (!checkPredecessors(BB, PointerVar, visitedBlocks))
+ return UninitPointer;
+ else {
+ // Cache the information that PointerVar and its aliases are live here
+ set<const Value *>::iterator Siter;
+ for (Siter = aliases.begin(); Siter != aliases.end(); Siter++)
+ BBPointerLiveInfo[BB][*Siter] = true;
+ }
+ }
+ return NoWarning;
+}
+
+// Called for load and getelementptr instructions
+enum WarningType CZeroInfo::checkInstruction(const BasicBlock *BB,
+ const Instruction *I,
+ std::set<const Value *>&
+ LocalStoresSoFar) {
+ const Value *PointerVar = I->getOperand(0);
+ if (isa<ConstantPointerNull>(I->getOperand(0)))
+ return IllegalMemoryLoc;
+
+ // Check for pointer arithmetic
+ if (!PointerAliasGraph.getPointsToInfo(PointerVar).isArray()) {
+ if (I->getNumOperands() > 1) {
+ // Check that every operand is 0 except for struct accesses.
+ const Type *elemType = I->getType();
+ for(unsigned int i = 1; i < I->getNumOperands(); i++) {
+ if (elemType->getTypeID() == Type::PointerTyID) {
+ if (I->getOperand(i) != ConstantInt::get(Type::UIntTy, 0))
+ return IllegalMemoryLoc;
+ elemType = cast<const PointerType>(elemType)->getElementType();
+ }
+ else if (elemType->getTypeID() == Type::ArrayTyID) {
+ elemType = cast<const ArrayType>(elemType)->getElementType();
+ }
+ else if (elemType->getTypeID() == Type::StructTyID) {
+ elemType = cast<const StructType>(elemType)->getTypeAtIndex(I->getOperand(i));
+ }
+ }
+ }
+ if (!isa<GlobalValue>(PointerVar) &&
+ !(PointerAliasGraph.getPointsToInfo(PointerVar).isGlobal()) &&
+ !(PointerAliasGraph.getPointsToInfo(PointerVar).isHeap()) &&
+ !(PointerAliasGraph.getPointsToInfo(PointerVar).isStruct()) &&
+ !(PointerAliasGraph.getPointsToInfo(PointerVar).isDummy())) {
+ return checkIfStored(BB, PointerVar, LocalStoresSoFar);
+ }
+ }
+
+ return NoWarning;
+}
+
+bool CZeroInfo::findSpuriousInsts() {
+ bool WarningFlag = false;
+ df_iterator<const Function*> It = df_begin(&TheFunction), End = df_end(&TheFunction);
+ for ( ; It != End; It++) {
+ const BasicBlock *BB = *It;
+ std::set<const Value *> LocalStoresSoFar;
+
+ // Sequentially scan instructions in the block
+ BasicBlock::const_iterator iterBB;
+ for (iterBB = BB->begin(); iterBB != BB->end(); iterBB++) {
+ const Instruction *I = iterBB;
+ enum WarningType WT;
+ if (!I)
+ continue;
+
+ if (isa<CastInst>(I)) {
+ // Disallow cast instructions involving pointers
+ if (I->getType()->getTypeID() == Type::PointerTyID) {
+ WarningsList += I->getName() + ": Casts to pointers disallowed" +
+ "in CZero\n";
+ WarningFlag = true;
+ }
+ else if (I->getOperand(0)->getType()->getTypeID()
+ == Type::PointerTyID) {
+ WarningsList += I->getName() + ":Casts from a pointer disallowed " +
+ "in CZero\n";
+ WarningFlag = true;
+ }
+ }
+ // If this is a store instruction update LocalStoresSoFar
+ else if (isa<StoreInst>(I)) {
+ LocalStoresSoFar.insert(I->getOperand(1));
+
+ // Check that there is no pointer arithmetic here
+ if (!PointerAliasGraph.getPointsToInfo(I->getOperand(1)).isArray()) {
+ const Type *elemType = I->getOperand(1)->getType();
+ for(unsigned int i = 2; i < I->getNumOperands(); i++) {
+ if (elemType->getTypeID() == Type::PointerTyID) {
+ if (I->getOperand(i) != ConstantInt::get(Type::UIntTy, 0)) {
+ WarningsList += "Stores to pointer variables should not have pointer arithmetic\n";
+ WarningFlag = true;
+ }
+ elemType = cast<const PointerType>(elemType)->getElementType();
+ }
+ else if (elemType->getTypeID() == Type::ArrayTyID) {
+ elemType = cast<const ArrayType>(elemType)->getElementType();
+ }
+ else if (elemType->getTypeID() == Type::StructTyID) {
+ elemType = cast<const StructType>(elemType)->getTypeAtIndex(I->getOperand(i));
+ }
+ }
+ }
+
+ // If a pointer is stored to another pointer, then we check that
+ // the pointer being stored has been stored to. (boy thats twisted!)
+ if (I->getOperand(0)->getType()->getTypeID() ==
+ Type::PointerTyID) {
+ if (!isa<GlobalValue>(I->getOperand(0)) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(0)).isGlobal()) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(0)).isHeap()) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(0)).isStruct()) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(0)).isDummy()) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(0)).isArray())) {
+ // TODO: Array
+ WT = checkIfStored(BB, I->getOperand(0), LocalStoresSoFar);
+ if (WT == UninitPointer)
+ WarningsList += "Pointer value being stored potentially uninitialized\n";
+ else
+ WarningsList += WarningString(WT);
+ if (WT != NoWarning)
+ WarningFlag = true;
+ }
+ }
+
+ }
+ else if (isa<LoadInst>(I)) {
+ // Check for globals, heaps and structs... all of which we ignore.
+ WT = checkInstruction(BB, I, LocalStoresSoFar);
+ if (WT == IllegalMemoryLoc) {
+ WarningsList += "Load from illegal memory location\n";
+ WarningFlag = true;
+ }
+ else {
+ WarningsList += WarningString(WT);
+ if (WT != NoWarning)
+ WarningFlag = true;
+ }
+ }
+ else if (isa<GetElementPtrInst>(I)) {
+ WT = checkInstruction(BB, I, LocalStoresSoFar);
+ // don't check for pointer arithmetic any more
+ if (WT == IllegalMemoryLoc) {
+ // WarningsList += "Pointer Arithmetic disallowed\n";
+ // WarningFlag = true;
+ }
+ else {
+ WarningsList += WarningString(WT);
+ if (WT != NoWarning)
+ WarningFlag = true;
+ }
+ }
+ else if (isa<CallInst>(I)) {
+ if (I->getNumOperands() > 1)
+ for (unsigned int i = 1; i < I->getNumOperands(); i++) {
+ if (I->getOperand(i)->getType()->getTypeID() ==
+ Type::PointerTyID) {
+ if (!isa<GlobalValue>(I->getOperand(i)) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(i)).isGlobal()) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(i)).isHeap()) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(i)).isStruct()) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(i)).isDummy()) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(i)).isArray())) {
+ WT = checkIfStored(BB, I->getOperand(i), LocalStoresSoFar);
+ if (WT == UninitPointer)
+ WarningsList += "Pointer value argument to function call potentially uninitialized \n";
+ else
+ WarningsList += WarningString(WT);
+ if (WT != NoWarning)
+ WarningFlag = true;
+ }
+ }
+ }
+ }
+ else if (isa<ReturnInst>(I)) {
+ if (I->getNumOperands() > 0)
+ if (I->getOperand(0)->getType()->getTypeID() ==
+ Type::PointerTyID) {
+ if (!isa<GlobalValue>(I->getOperand(0)) &&
+ !(PointerAliasGraph.getPointsToInfo
+ (I->getOperand(0)).isGlobal())) {
+ WarningsList += "Pointer value being returned by function does not point to a global value (only intra-procedural region analysis done)\n";
+ WarningFlag = true;
+ }
+ }
+ }
+ }
+ }
+ return WarningFlag;
+}
+
+namespace {
+
+ // The Pass class we implement
+ struct CZeroPtrChecks : public FunctionPass {
+
+ const char *getPassName() const { return "CZero security pass"; }
+
+ virtual bool runOnFunction (Function &F) {
+ bool Error = false;
+ DominatorSet *DomSet = &getAnalysis<DominatorSet>();
+ CZeroInfo *CZI = new CZeroInfo(F, DomSet);
+ std::cerr << "\nIn function " << F.getName() << "\n";
+ if (CZI->getWarnings() != "") {
+ std::cerr << "Security Warning/s: \n";
+ std::cerr << CZI->getWarnings();
+ Error = true;
+ }
+
+ delete CZI;
+
+ return false;
+
+ }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ // TODO: Check when we generate code.
+ AU.setPreservesAll();
+ AU.addRequired<DominatorSet>();
+ }
+
+ };
+
+ RegisterPass<CZeroPtrChecks> X("czeroptrchecks", "CZero Pointer Checks");
+
+}
+
+//Externally visible
+
+Pass *createCZeroUninitPtrPass() {
+ return new CZeroPtrChecks();
+}
diff --git a/safecode/lib/PointerChecks/CZeroInfo.h b/safecode/lib/PointerChecks/CZeroInfo.h
new file mode 100755
index 0000000..181d68c
--- /dev/null
+++ b/safecode/lib/PointerChecks/CZeroInfo.h
@@ -0,0 +1,264 @@
+//===- llvm/Analysis/CZeroInfo.h - CZero info --------*- C++ -*--=//
+//
+// This file checks the LLVM code for any potential security holes. We allow
+// a restricted number of usages in order to preserve memory safety etc.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_ANALYSIS_CZEROINFO_H
+#define LLVM_ANALYSIS_CZEROINFO_H
+
+#include "llvm/Type.h"
+#include "llvm/Value.h"
+#include "llvm/Instructions.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CFG.h"
+#include <algorithm>
+using std::string;
+using std::map;
+using std::vector;
+using std::set;
+
+
+namespace llvm {
+
+// A dummy node is used when the value pointed to is unknown as yet.
+struct PointsToTarget {
+private:
+ const Value *Val;
+ bool Dummy;
+ bool Global;
+
+ // If the node is a dummy, the following fields don't matter
+ bool Array;
+ bool Struct;
+ bool Heap;
+ int TargetID;
+
+ static int NextTargetID;
+
+public:
+
+ static const int DummyTarget = 1;
+ static const int GlobalTarget = 2;
+
+ bool operator<(const PointsToTarget PTT) const {
+ return (TargetID < PTT.TargetID);
+ }
+
+ PointsToTarget(const Value *V) : Val(V) {
+ TargetID = NextTargetID++;
+ Dummy = false;
+ Global = false;
+ Heap = false;
+ Array = false;
+ Struct = false;
+ if (isa<AllocaInst>(V)) {
+ const AllocaInst *AIV = dyn_cast<AllocaInst>(V);
+ Array = AIV->isArrayAllocation();
+ if (!AIV->isArrayAllocation()) {
+ if (AIV->getAllocatedType()->getTypeID() == Type::StructTyID)
+ Struct = true;
+ }
+ }
+ else if (isa<MallocInst>(V)) {
+ const MallocInst *MIV = dyn_cast<MallocInst>(V);
+ Array = MIV->isArrayAllocation();
+ if (!MIV->isArrayAllocation()) {
+ if (MIV->getAllocatedType()->getTypeID() == Type::StructTyID)
+ Struct = true;
+ }
+ Heap = true;
+ }
+ }
+
+ // Default constructor creates a dummy node.
+ PointsToTarget(int TargetType) {
+ TargetID = NextTargetID++;
+ Val = 0;
+ Dummy = false;
+ Global = false;
+ if (TargetType == DummyTarget) {
+ Dummy = true;
+ }
+ else if (TargetType == GlobalTarget) {
+ Global = true;
+ }
+ Struct = false;
+ Array = false;
+ Heap = false;
+ }
+
+ PointsToTarget() {
+ Val = 0;
+ Dummy = false;
+ Global = false;
+ Struct = false;
+ Array = false;
+ Heap = false;
+ }
+
+ bool isDummy() { return Dummy; }
+
+ bool isGlobal() { return Global; }
+
+ bool isArray() { return Array; }
+
+ bool isStruct() { return Struct; }
+
+ bool isHeap() { return Heap; }
+
+ bool isPHINode() {
+ if (Val)
+ return isa<PHINode>(Val);
+ else
+ return false;
+ }
+
+ const Value* val() { return Val; }
+
+};
+
+int PointsToTarget::NextTargetID = 0;
+
+// The graph is to be recreated for each function. This is done by each
+// CZeroInfo object being associated with a CZeroAliasGraph
+class CZeroAliasGraph {
+ // We ensure that memory locations on stack alone are initialized before
+ // use. A memory location on the stack is identified by the alloca
+ // instruction that created it.
+
+protected:
+ // There are edges from a SSA pointer variable to memory locations
+ // and from SSA pointer variables to phi nodes.
+ // Phi nodes are treated specially in the alias graph.
+ std::map<const Value *, PointsToTarget> pointsTo;
+
+ // Given a memory location, all the SSA pointer vars that point to it.
+ std::map<PointsToTarget, set<const Value *> > pointedBy;
+
+ // NOTE: every update to the graph should update both of these maps
+
+public:
+
+ // Add and edge from V1 to V2.
+ // Situations in which this happens is
+ // V1: SSA pointer variable, V2: alloca
+ // V1: SSA pointer variable, V2: phi node.
+ // Called only once for each SSA pointer value.
+ void addEdge (const Value *V1, const Value *V2) {
+ assert (pointsTo.count(V1) == 0 && "Value should not be inserted in graph yet");
+ PointsToTarget PT(V2);
+ pointsTo[V1] = PT;
+ pointedBy[PT].insert(V1);
+ }
+
+ // Add an edge from an SSA pointer variable to a dummy if we don't really
+ // know what it points to.
+ // Eg. If we load an int* from an int** since we currently don't do any
+ // flow-sensitive pointer tracking.
+ // This or addEdge(V1, V2) called only once for an SSA pointer value
+ void addEdge (const Value *V, int TargetType) {
+ assert (pointsTo.count(V) == 0 && "Value should not be inserted in graph yet");
+ PointsToTarget PT(TargetType);
+ pointsTo[V] = PT;
+ pointedBy[PT].insert(V);
+ }
+
+ PointsToTarget getPointsToInfo(const Value *V) {
+ return pointsTo[V];
+ }
+
+ set<const Value *> getPointedByInfo(PointsToTarget PT) {
+ return pointedBy[PT];
+ }
+
+ // make alias an alias of orig.
+ // If orig does not exist, then both of them need to point to a dummy node.
+ // NOTE: Call only when alias is the lvalue of an instruction.
+ // Call only once for a particular alias
+ void addAlias (const Value *alias, const Value *orig) {
+ assert (pointsTo.count(alias) == 0 && "Value alias not already in graph");
+ assert (pointsTo.count(orig) != 0 && "Value orig not inserted in graph yet");
+ if (pointsTo[orig].val())
+ addEdge(alias, pointsTo[orig].val());
+ else if (pointsTo[orig].isGlobal())
+ addEdge(alias, PointsToTarget::GlobalTarget);
+ else if (pointsTo[orig].isDummy())
+ addEdge(alias, PointsToTarget::DummyTarget);
+ }
+
+ // Returns aliases of the value.
+ // Return value also contains V
+ set<const Value *> getAliases(const Value *V) {
+ return pointedBy[pointsTo[V]];
+ }
+
+};
+
+
+enum WarningType {
+ NoWarning,
+ IllegalMemoryLoc,
+ UninitPointer
+};
+
+typedef std::map<const Value *, bool> LivePointerMap;
+
+// This class contains the information that CZero checks require.
+// This is re-instantiated and initialized for each function.
+class CZeroInfo {
+ // The two phases of our algorithm
+ // Phase 1: Examine all the stores by looking at basic blocks in a depth
+ // first manner and update the PointerLiveInfo map.
+ void depthFirstGatherer();
+ // Phase 2: Iterate through basic blocks depth first and see if the loads
+ // are safe i.e. there is a store of the pointer at every path to the load
+ // in question.
+ bool findSpuriousInsts();
+ bool checkPredecessors(const BasicBlock *BB, const Value *V,
+ set<const BasicBlock *>& vistedBlocks);
+ enum WarningType checkIfStored(const BasicBlock *BB,
+ const Value *V,
+ std::set<const Value *>& LocalStoresSoFar);
+
+ enum WarningType checkInstruction(const BasicBlock *BB,
+ const Instruction *I,
+ std::set<const Value *>& LocalStoresSoFar);
+
+ string WarningString(enum WarningType WT);
+
+protected:
+ const Function& TheFunction;
+
+ // This is the map (BasicBlock1 * Pointer variable) -> BasicBlock2
+ // where BasicBlock2 dominates BasicBlock1 and has a store to the pointer
+ std::map<const BasicBlock *, LivePointerMap> BBPointerLiveInfo;
+
+ // Alias graph to be used in the findSpuriousLoads phase
+ // Created in phase 1.
+ CZeroAliasGraph PointerAliasGraph;
+
+ // Dominator set information
+ DominatorSet *DomSet;
+
+ string WarningsList;
+
+
+public:
+
+ CZeroInfo (Function& F, DominatorSet* DSet) : TheFunction(F), DomSet(DSet) {
+
+ }
+
+ // Public access method to get all the warnings associated with
+ // the particular function.
+ string& getWarnings ();
+};
+
+}
+#endif
+
diff --git a/safecode/lib/PointerChecks/FreeRemoval.cpp b/safecode/lib/PointerChecks/FreeRemoval.cpp
new file mode 100755
index 0000000..266fedc
--- /dev/null
+++ b/safecode/lib/PointerChecks/FreeRemoval.cpp
@@ -0,0 +1,922 @@
+//===-- FreeRemoval.cpp - EmbeC transformation that removes frees ------------//
+// Implementation of FreeRemoval.h : an EmbeC pass
+//
+// Some assumptions:
+// * Correctness of pool allocation
+// * Destroys at end of functions.
+// Pool pointer aliasing assumptions
+// -pool pointer copies via gep's are removed
+// -no phinode takes two pool pointers because then they would be the same pool
+// Result: If we look at pool pointer defs and look for their uses... we check
+// that their only uses are calls to pool_allocs, pool_frees and pool_destroys.
+//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "FreeRemoval"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Instructions.h"
+#include "SafeDynMemAlloc.h"
+#include <iostream>
+using namespace llvm;
+#ifndef LLVA_KERNEL
+
+
+namespace {
+ RegisterPass<EmbeCFreeRemoval> Y("EmbeC", "EmbeC pass that removes all frees and issues warnings if behaviour has changed");
+
+
+// Check if SSA pool pointer variable V has uses other than alloc, free and
+// destroy
+void EmbeCFreeRemoval::checkPoolSSAVarUses(Function *F, Value *V,
+ map<Value *, set<Instruction *> > &FuncPoolAllocs,
+ map<Value *, set<Instruction *> > &FuncPoolFrees,
+ map<Value *, set<Instruction *> > &FuncPoolDestroys) {
+ if (V->use_begin() != V->use_end()) {
+ for (Value::use_iterator UI = V->use_begin(), UE = V->use_end();
+ UI != UE; ++UI) {
+ // Check that the use is nothing except a call to pool_alloc, pool_free
+ // or pool_destroy
+ if (Instruction *I = dyn_cast<Instruction>(*UI)) {
+ // For global pools, we need to check that only uses within the
+ // function under consideration are checked.
+ if (I->getParent()->getParent() != F)
+ continue;
+ } else
+ continue;
+ if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
+ if (Function *calledF = dyn_cast<Function>(CI->getOperand(0))) {
+ if (calledF == F) {
+ int operandNo;
+ for (unsigned int i = 1; i < CI->getNumOperands(); i++)
+ if (CI->getOperand(i) == V) {
+ operandNo = i;
+ break;
+ }
+
+ Value *formalParam;
+ int opi = 0;
+ for (Function::arg_iterator I = calledF->arg_begin(),
+ E = calledF->arg_end();
+ I != E && opi < operandNo; ++I, ++opi)
+ if (opi == operandNo - 1)
+ formalParam = I;
+
+ if (formalParam == V)
+ ;
+ else {
+ std::cerr << "EmbeC: " << F->getName()
+ << ": Recursion not supported for case classification\n";
+ continue;
+ }
+ }
+ if (!calledF->isExternal()) {
+ // the pool pointer is passed to the called function
+
+ // Find the formal parameter corresponding to the parameter V
+ int operandNo;
+ unsigned int limit = CI->getNumOperands();
+ for (unsigned int i = 1; i < limit; i++)
+ if (CI->getOperand(i) == V) {
+ operandNo = i;
+ break;
+ }
+
+ Value *formalParam;
+ int opi = 0;
+ for (Function::arg_iterator I = calledF->arg_begin(),
+ E = calledF->arg_end();
+ I != E && opi < operandNo; ++I, ++opi)
+ if (opi == operandNo - 1)
+ formalParam = I;
+
+ // if the called function has undestroyed frees in pool formalParam
+ if (FuncFreedPools[calledF].find(formalParam) !=
+ FuncFreedPools[calledF].end() &&
+ FuncDestroyedPools[calledF].find(formalParam) ==
+ FuncDestroyedPools[calledF].end()) {
+ FuncPoolFrees[V].insert(cast<Instruction>(*UI));
+ }
+ // if the called function has undestroyed allocs in formalParam
+ if (FuncAllocedPools[calledF].find(formalParam) !=
+ FuncAllocedPools[calledF].end()) {
+ FuncPoolAllocs[V].insert(cast<Instruction>(*UI));
+ }
+
+ // if the called function has a destroy in formalParam
+ if (FuncDestroyedPools[calledF].find(formalParam) !=
+ FuncDestroyedPools[calledF].end()) {
+ FuncPoolDestroys[V].insert(cast<Instruction>(*UI));
+ }
+ } else {
+ // external function
+ if (calledF->getName() == PoolI) {
+ // Insert call to poolmakeunfreeable after every poolinit since
+ // we do not free memory to the system for safety in all cases.
+ //new CallInst(PoolMakeUnfreeable, make_vector(V, 0), "",
+ // CI->getNext()); //taken care of in runtime library
+ moduleChanged = true;
+ } else if (calledF->getName() == PoolA) {
+ FuncPoolAllocs[V].insert(cast<Instruction>(*UI));
+ } else if (calledF->getName() == PoolF) {
+ FuncPoolFrees[V].insert(cast<Instruction>(*UI));
+ } else if (calledF->getName() == PoolD) {
+ FuncPoolDestroys[V].insert(cast<Instruction>(*UI));
+ } else if (calledF->getName() == PoolMUF) {
+ // Ignore
+ } else if (calledF->getName() == PoolCh) {
+ // Ignore
+ } else if (calledF->getName() == PoolAA) {
+ FuncPoolAllocs[V].insert(cast<Instruction>(CI->getNext()));
+ } else {
+ hasError = true;
+ std::cerr << "EmbeC: " << F->getName() << ": Unrecognized pool variable use \n";
+ // abort();
+ }
+ }
+ } else {
+
+ // Find the formal parameter corresponding to the parameter V
+ int operandNo;
+ for (unsigned int i = 1; i < CI->getNumOperands(); i++)
+ if (CI->getOperand(i) == V)
+ operandNo = i;
+ CompleteBUDataStructures::callee_iterator CalleesI =
+ BUDS->callee_begin(CI), CalleesE = BUDS->callee_end(CI);
+
+ for (; CalleesI != CalleesE; ++CalleesI) {
+ Function *calledF = CalleesI->second;
+
+ PoolInfo->getFuncInfoOrClone(*calledF);
+
+ /*
+ if (PAFI->PoolArgFirst == PAFI->PoolArgLast ||
+ operandNo-1 < PAFI->PoolArgFirst ||
+ operandNo-1 >= PAFI->PoolArgLast)
+ continue;
+ */
+
+ Value *formalParam;
+ int opi = 0;
+ for (Function::arg_iterator I = calledF->arg_begin(),
+ E = calledF->arg_end();
+ I != E && opi < operandNo; ++I, ++opi)
+ if (opi == operandNo-1)
+ formalParam = I;
+
+ // if the called function has undestroyed frees in pool formalParam
+ if (FuncFreedPools[calledF].find(formalParam) !=
+ FuncFreedPools[calledF].end() &&
+ FuncDestroyedPools[calledF].find(formalParam) ==
+ FuncDestroyedPools[calledF].end()) {
+ FuncPoolFrees[V].insert(cast<Instruction>(*UI));
+ }
+ // if the called function has undestroyed allocs in formalParam
+ if (FuncAllocedPools[calledF].find(formalParam) !=
+ FuncAllocedPools[calledF].end()) {
+ FuncPoolAllocs[V].insert(cast<Instruction>(*UI));
+ }
+
+ // if the called function has a destroy in formalParam
+ if (FuncDestroyedPools[calledF].find(formalParam) !=
+ FuncDestroyedPools[calledF].end()) {
+ FuncPoolDestroys[V].insert(cast<Instruction>(*UI));
+ }
+
+ }
+ }
+ } else {
+ hasError = true;
+ std::cerr << "EmbeC: " << F->getName() << ": Unrecognized pool variable use \n";
+ }
+ }
+ }
+}
+
+// Propagate that the pool V is a collapsed pool to each of the callees of F
+// that have V as argument
+void EmbeCFreeRemoval::propagateCollapsedInfo(Function *F, Value *V) {
+ for (Value::use_iterator UI = V->use_begin(),
+ UE = V->use_end(); UI != UE; ++UI) {
+ if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
+ if (Function *calledF =
+ dyn_cast<Function>(CI->getOperand(0))) {
+ if (calledF == F) {
+ // Quick check for the common case
+ // Find the formal parameter corresponding to the parameter V
+ int operandNo;
+ for (unsigned int i = 1; i < CI->getNumOperands(); i++)
+ if (CI->getOperand(i) == V) {
+ operandNo = i;
+ break;
+ }
+
+ Value *formalParam;
+ int opi = 0;
+ for (Function::arg_iterator I = calledF->arg_begin(),
+ E = calledF->arg_end();
+ I != E && opi < operandNo; ++I, ++opi)
+ if (opi == operandNo - 1)
+ formalParam = I;
+ if (formalParam == V) {
+ // This is the common case.
+ }
+ else {
+ std::cerr << "EmbeC: " << F->getName()
+ << ": Recursion not supported\n";
+ abort();
+ continue;
+ }
+ }
+ if (!calledF->isExternal()) {
+ // the pool pointer is passed to the called function
+
+ // Find the formal parameter corresponding to the parameter V
+ int operandNo;
+ for (unsigned int i = 1; i < CI->getNumOperands(); i++)
+ if (CI->getOperand(i) == V) {
+ operandNo = i;
+ break;
+ }
+
+ Value *formalParam;
+ int opi = 0;
+ for (Function::arg_iterator I = calledF->arg_begin(),
+ E = calledF->arg_end();
+ I != E && opi < operandNo; ++I, ++opi)
+ if (opi == operandNo - 1)
+ formalParam = I;
+
+ CollapsedPoolPtrs[calledF].insert(formalParam);
+ }
+ } else {
+ // indirect function call
+
+ // std::pair<CompleteBUDataStructures::ActualCalleesTy::const_iterator, CompleteBUDataStructures::ActualCalleesTy::const_iterator> Callees = AC.equal_range(CI);
+
+ // Find the formal parameter corresponding to the parameter V
+ int operandNo;
+ for (unsigned int i = 1; i < CI->getNumOperands(); i++)
+ if (CI->getOperand(i) == V)
+ operandNo = i;
+
+ CompleteBUDataStructures::callee_iterator CalleesI =
+ BUDS->callee_begin(CI), CalleesE = BUDS->callee_end(CI);
+
+ for (; CalleesI != CalleesE; ++CalleesI) {
+ Function *calledF = CalleesI->second;
+
+ PoolInfo->getFuncInfoOrClone(*calledF);
+
+ /*
+ if (PAFI->PoolArgFirst == PAFI->PoolArgLast ||
+ operandNo-1 < PAFI->PoolArgFirst ||
+ operandNo-1 >= PAFI->PoolArgLast)
+ continue;
+ */
+
+ Value *formalParam;
+ int opi = 0;
+ for (Function::arg_iterator I = calledF->arg_begin(),
+ E = calledF->arg_end();
+ I != E && opi < operandNo; ++I, ++opi)
+ if (opi == operandNo-1)
+ formalParam = I;
+ CollapsedPoolPtrs[calledF].insert(formalParam);
+ }
+ }
+ }
+ }
+}
+
+
+// Returns true if BB1 follows BB2 in some path in F
+static bool followsBlock(BasicBlock *BB1, BasicBlock *BB2, Function *F,
+ set<BasicBlock *> visitedBlocks) {
+ for (succ_iterator BBSI = succ_begin(BB2), BBSE =
+ succ_end(BB2); BBSI != BBSE; ++BBSI) {
+ if (visitedBlocks.find(*BBSI) == visitedBlocks.end())
+ if (*BBSI == BB1)
+ return true;
+ else {
+ visitedBlocks.insert(*BBSI);
+ if (followsBlock(BB1, *BBSI, F, visitedBlocks))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#if 0
+// Checks if Inst1 follows Inst2 in any path in the function F.
+static bool followsInst(Instruction *Inst1, Instruction *Inst2, Function *F) {
+ if (Inst1->getParent() == Inst2->getParent()) {
+ for (BasicBlock::iterator BBI = Inst2, BBE = Inst2->getParent()->end();
+ BBI != BBE; ++BBI)
+ if (Inst1 == &(*BBI))
+ return true;
+ }
+ set<BasicBlock *> visitedBlocks;
+ return followsBlock(Inst1->getParent(), Inst2->getParent(), F,
+ visitedBlocks);
+}
+#endif
+
+#if 0
+static void printSets(set<Value *> &FuncPoolPtrs,
+ map<Value *, set<Instruction *> > &FuncPoolFrees,
+ map<Value *, set<Instruction *> > &FuncPoolAllocs) {
+ for (set<Value *>::iterator I = FuncPoolPtrs.begin(), E = FuncPoolPtrs.end();
+ I != E; ++I) {
+ std::cerr << "Pool Variable: " << *I << "\n";
+ if (FuncPoolFrees[*I].size()) {
+ std::cerr << "Frees :" << "\n";
+ for (set<Instruction *>::iterator FreeI =
+ FuncPoolFrees[*I].begin(), FreeE = FuncPoolFrees[*I].end();
+ FreeI != FreeE; ++FreeI) {
+ CallInst *CInst = dyn_cast<CallInst>(*FreeI);
+ Function *CIF = dyn_cast<Function>(CInst->getOperand(0));
+ std::cerr << CIF->getName() << "\n";
+ }
+ }
+ if (FuncPoolAllocs[*I].size()) {
+ std::cerr << "Allocs :" << "\n";
+ for (set<Instruction *>::iterator AllocI =
+ FuncPoolAllocs[*I].begin(), AllocE = FuncPoolAllocs[*I].end();
+ AllocI != AllocE; ++AllocI) {
+ CallInst *CInst = dyn_cast<CallInst>(*AllocI);
+ Function *CIF = dyn_cast<Function>(CInst->getOperand(0));
+ std::cerr << CIF->getName() << "\n";
+ }
+ }
+ }
+}
+#endif
+
+ DSNode *EmbeCFreeRemoval::guessDSNode(Value *v, DSGraph &G, PA::FuncInfo *PAFI) {
+ if (std::find(Visited.begin(), Visited.end(), v) != Visited.end())
+ return 0;
+ Visited.push_back(v);
+ if (isa<PointerType>(v->getType())) {
+ DSNode *r = G.getNodeForValue(v).getNode();
+ if (r && PAFI->PoolDescriptors.count(r))
+ return r;
+ }
+ DSNode *retDSNode = 0;
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(v)) {
+ retDSNode = guessDSNode(Bop->getOperand(0), G, PAFI);
+ if (!retDSNode) retDSNode = guessDSNode(Bop->getOperand(0), G, PAFI);
+ } else if (CastInst *CI = dyn_cast<CastInst>(v)) {
+ retDSNode = guessDSNode(CI->getOperand(0), G, PAFI);
+ } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(v)) {
+ retDSNode = guessDSNode(GEP->getPointerOperand(), G, PAFI);
+ } else if (LoadInst *LI = dyn_cast<LoadInst>(v)) {
+ //hope its collapsed node ...
+ retDSNode = guessDSNode(LI->getOperand(0), G, PAFI);
+ } else if (PHINode* PN =dyn_cast<PHINode>(v)) {
+ for (unsigned idx = 0; idx < PN->getNumIncomingValues(); ++idx) {
+ if (!retDSNode) {
+ retDSNode = guessDSNode(PN->getIncomingValue(idx), G, PAFI);
+ } else {
+ break;
+ }
+ }
+ } else if (CallInst* CI =dyn_cast<CallInst>(v)) {
+ for (unsigned idx = 1; idx < CI->getNumOperands(); ++idx) {
+ if (!retDSNode) {
+ retDSNode = guessDSNode(CI->getOperand(idx), G, PAFI);
+ } else {
+ break;
+ }
+ }
+ }
+ return retDSNode;
+ }
+
+ void EmbeCFreeRemoval::guessPoolPtrAndInsertCheck(PA::FuncInfo *PAFI, Value *oldI, Instruction *I, Value *pOpI, DSGraph &oldG) {
+ Visited.clear();
+ //follow up v through the ssa def0use chains
+ DSNode *DSN = guessDSNode(oldI, oldG, PAFI);
+ // assert(DSN && "can not guess the pool ptr");
+ // assert(PAFI->PoolDescriptors.count(DSN) && "no pool descriptor found \n");
+ CastInst *CastI =
+ new CastInst(pOpI,
+ PointerType::get(Type::SByteTy), "casted", I);
+ if (DSN) {
+
+ new CallInst(PoolCheck,
+ make_vector(PAFI->PoolDescriptors[DSN], CastI, 0),
+ "", I);
+ } else {
+ Type *VoidPtrTy = PointerType::get(Type::SByteTy);
+ const Type *PoolDescType =
+ ArrayType::get(VoidPtrTy, 50);
+
+ const PointerType *PoolDescPtr = PointerType::get(PoolDescType);
+ Value *PH = Constant::getNullValue(PoolDescPtr);
+ new CallInst(PoolCheck,
+ make_vector(PH, CastI, 0),
+ "", I);
+
+ }
+ DEBUG(std::cerr << "inserted a pool check for unknown node \n");
+
+ }
+
+ void EmbeCFreeRemoval::insertNonCollapsedChecks(Function *Forig, Function *F, DSNode *DSN) {
+ assert(!DSN->isNodeCompletelyFolded() && "its collapsed! \n");
+ if (DSN->isUnknownNode()) return; //we'll handle it separately
+ //Assuming alignment is the beginning of a node, owise its runtime failure
+ bool isClonedFunc;
+ PA::FuncInfo* PAFI = PoolInfo->getFuncInfoOrClone(*F);
+ if (PoolInfo->getFuncInfo(*F))
+ isClonedFunc = false;
+ else
+ isClonedFunc = true;
+
+ DSGraph& oldG = BUDS->getDSGraph(*Forig);
+
+ // For each scalar pointer in the original function
+ for (DSGraph::ScalarMapTy::iterator SMI = oldG.getScalarMap().begin(),
+ SME = oldG.getScalarMap().end(); SMI != SME; ++SMI) {
+ DSNodeHandle &GH = SMI->second;
+ if (DSN == GH.getNode()) { //We need to insert checks to all the uses of this ptr
+ if (GH.getOffset()) {
+ if (DSN->isArray()) return; //we are any way checking all arrays
+ assert(!GH.getOffset() && " we dont handle middle of structs yet \n");
+ }
+ Value *NewPtr = SMI->first;
+ if (isClonedFunc) {
+ NewPtr = PAFI->ValueMap[SMI->first];
+ }
+ if (!NewPtr)
+ continue;
+ for (Value::use_iterator UI = NewPtr->use_begin(),
+ UE = NewPtr->use_end(); UI != UE; ++UI) {
+ // If the use is the 2nd operand of store, insert a runtime check
+ if (StoreInst *StI = dyn_cast<StoreInst>(*UI)) {
+ if (StI->getOperand(1) == NewPtr) {
+ moduleChanged = true;
+ CastInst *CastI =
+ new CastInst(StI->getOperand(1),
+ PointerType::get(Type::SByteTy), "casted", StI);
+ new CallInst(PoolCheck,
+ make_vector(PAFI->PoolDescriptors[DSN], CastI, 0),
+ "", StI);
+ std::cerr << " inserted poolcheck for noncollapsed pool\n";
+ }
+ } else if (CallInst *CallI = dyn_cast<CallInst>(*UI)) {
+ // If this is a function pointer read from a collapsed node,
+ // reject the code
+ if (CallI->getOperand(0) == NewPtr) {
+ std::cerr <<
+ "EmbeC: Error - Function pointer read from collapsed node\n";
+ abort();
+ }
+ } else if (LoadInst *LdI = dyn_cast<LoadInst>(*UI)) {
+ if (LdI->getOperand(0) == NewPtr) {
+ moduleChanged = true;
+ CastInst *CastI =
+ new CastInst(LdI->getOperand(0),
+ PointerType::get(Type::SByteTy), "casted", LdI);
+ new CallInst(PoolCheck,
+ make_vector(PAFI->PoolDescriptors[DSN], CastI, 0),
+ "", LdI);
+ std::cerr << " inserted poolcheck for noncollpased pool\n";
+ }
+ }
+ }
+ }
+ }
+ }
+
+// Insert runtime checks. Called on the functions in the existing program
+void EmbeCFreeRemoval::addRuntimeChecks(Function *F, Function *Forig) {
+ //The following code is phased out, a newer version is insert.cpp
+
+#if 0
+ bool isClonedFunc;
+ PA::FuncInfo* PAFI = PoolInfo->getFuncInfoOrClone(*F);
+
+ if (PoolInfo->getFuncInfo(*F))
+ isClonedFunc = false;
+ else
+ isClonedFunc = true;
+
+ if (!PAFI->PoolDescriptors.empty()) {
+ // For each scalar pointer in the original function
+ for (DSGraph::ScalarMapTy::iterator SMI = oldG.getScalarMap().begin(),
+ SME = oldG.getScalarMap().end(); SMI != SME; ++SMI) {
+ DSNodeHandle &GH = SMI->second;
+ DSNode *DSN = GH.getNode();
+ if (!DSN)
+ continue;
+ if (DSN->isUnknownNode()) {
+ // Report an error if we see loads or stores on the pointer
+ Value *NewPtr = SMI->first;
+ if (isClonedFunc) {
+ if (PAFI->ValueMap.count(SMI->first))
+ NewPtr = PAFI->ValueMap[SMI->first];
+ else continue;
+ }
+ if (!NewPtr)
+ continue;
+ for (Value::use_iterator UI = NewPtr->use_begin(),
+ UE = NewPtr->use_end(); UI != UE; ++UI) {
+ if (StoreInst *StI = dyn_cast<StoreInst>(*UI)) {
+ if (StI->getOperand(1) == NewPtr) {
+ guessPoolPtrAndInsertCheck(PAFI, SMI->first, StI, NewPtr, oldG);
+ std::cerr <<
+ "EmbeC: In function " << F->getName() << ": Presence of an unknown node can invalidate pool allocation\n";
+ break;
+ }
+ } else if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
+ //We'll try to guess a pool descriptor and insert a check
+ //if it fails then ok too bad ;)
+ //Add guess the pool handle
+ guessPoolPtrAndInsertCheck(PAFI, SMI->first, LI, NewPtr, oldG);
+ std::cerr <<
+ "EmbeC: In function " << F->getName() << ": Presence of an unknown node can invalidate pool allocation\n";
+ break;
+ } else if (CallInst *CallI = dyn_cast<CallInst>(*UI)) {
+ // If this is a function pointer read from a collapsed node,
+ // reject the code
+ if (CallI->getOperand(0) == NewPtr) {
+ std::cerr <<
+ "EmbeC: Error - Function pointer read from Unknown node\n";
+ abort();
+
+ }
+ }
+ }
+ }
+ if (PAFI->PoolDescriptors.count(DSN)) {
+ // If the node pointed to, corresponds to a collapsed pool
+ if (CollapsedPoolPtrs[F].find(PAFI->PoolDescriptors[DSN]) !=
+ CollapsedPoolPtrs[F].end()) {
+ // find uses of the coresponding new pointer
+ Value *NewPtr = SMI->first;
+ if (isClonedFunc) {
+ if (PAFI->ValueMap.count(SMI->first)) {
+ NewPtr = PAFI->ValueMap[SMI->first];
+ if (!PAFI->NewToOldValueMap.count(NewPtr)) {
+ std::cerr << "WARNING : checks for NewPtr are not inserted\n";
+ abort();
+ continue;
+ }
+ } else {
+ std::cerr << "WARNING : checks for NewPtr are not inserted\n";
+ abort();
+ continue;
+ }
+ }
+ if (!NewPtr)
+ continue;
+ for (Value::use_iterator UI = NewPtr->use_begin(),
+ UE = NewPtr->use_end(); UI != UE; ++UI) {
+ // If the use is the 2nd operand of store, insert a runtime check
+ if (StoreInst *StI = dyn_cast<StoreInst>(*UI)) {
+ if (StI->getOperand(1) == NewPtr) {
+ if (!isa<GlobalVariable>(StI->getOperand(1))) {
+ moduleChanged = true;
+ CastInst *CastI =
+ new CastInst(StI->getOperand(1),
+ PointerType::get(Type::SByteTy), "casted", StI);
+ new CallInst(PoolCheck,
+ make_vector(PAFI->PoolDescriptors[DSN], CastI, 0),
+ "", StI);
+ DEBUG(std::cerr << " inserted poolcheck for collpased pool\n";);
+ } else {
+ std::cerr << "WARNING DID not insert a check for collapsed global store";
+ }
+ }
+ } else if (CallInst *CallI = dyn_cast<CallInst>(*UI)) {
+ // If this is a function pointer read from a collapsed node,
+ // reject the code
+ if (CallI->getOperand(0) == NewPtr) {
+ std::cerr <<
+ "EmbeC: Error - Function pointer read from collapsed node\n";
+ abort();
+ }
+ } else if (LoadInst *LdI = dyn_cast<LoadInst>(*UI)) {
+ if (LdI->getOperand(0) == NewPtr) {
+ if (!isa<GlobalVariable>(LdI->getOperand(0))) {
+ moduleChanged = true;
+ CastInst *CastI =
+ new CastInst(LdI->getOperand(0),
+ PointerType::get(Type::SByteTy), "casted", LdI);
+ new CallInst(PoolCheck,
+ make_vector(PAFI->PoolDescriptors[DSN], CastI, 0),
+ "", LdI);
+ std::cerr << " inserted poolcheck for collpased pool\n";
+ } else {
+ std::cerr << "WARNING DID not insert a check for collapsed global load";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+}
+
+bool EmbeCFreeRemoval::runOnModule(Module &M) {
+ CurModule = &M;
+ moduleChanged = false;
+ hasError = false;
+
+ // Insert prototypes in the module
+ // NB: This has to be in sync with the types in PoolAllocate.cpp
+ const Type *VoidPtrTy = PointerType::get(Type::SByteTy);
+
+ const Type *PoolDescType =
+ // StructType::get(make_vector<const Type*>(VoidPtrTy, VoidPtrTy,
+ // Type::UIntTy, Type::UIntTy, 0));
+ ArrayType::get(VoidPtrTy, 50);
+
+ const PointerType *PoolDescPtr = PointerType::get(PoolDescType);
+ FunctionType *PoolMakeUnfreeableTy =
+ FunctionType::get(Type::VoidTy,
+ make_vector<const Type*>(PoolDescPtr, 0),
+ false);
+
+ FunctionType *PoolCheckTy =
+ FunctionType::get(Type::VoidTy,
+ make_vector<const Type*>(VoidPtrTy, VoidPtrTy, 0),
+ false);
+
+ PoolMakeUnfreeable = CurModule->getOrInsertFunction("poolmakeunfreeable",
+ PoolMakeUnfreeableTy);
+
+ PoolCheck = CurModule->getOrInsertFunction("poolcheck", PoolCheckTy);
+
+ moduleChanged = true;
+
+ Function *mainF = M.getMainFunction();
+
+ if (!mainF) {
+ hasError = true;
+ std::cerr << "EmbeC: Function main required\n";
+ return false;
+ }
+
+ // Bottom up on the call graph
+ // TODO: Take care of recursion/mutual recursion
+#ifndef LLVA_KERNEL
+ PoolInfo = &getAnalysis<PoolAllocate>();
+ BUDS = &(PoolInfo->getECGraphs());
+#endif
+ CallGraph &CG = getAnalysis<CallGraph>();
+ // BUDS = &getAnalysis<CompleteBUDataStructures>();
+ // BUDS = PoolInfo->getDataStructures();
+ // TDDS = &getAnalysis<TDDataStructures>();
+ // For each function, all its pool SSA variables including its arguments
+ map<Function *, set<Value *> > FuncPoolPtrs;
+
+ for (po_iterator<CallGraph*> CGI = po_begin(&CG),
+ CGE = po_end(&CG); CGI != CGE; ++CGI) {
+
+ Function *F = (*CGI)->getFunction();
+
+ // Ignore nodes representing external functions in the call graph
+ if (!F)
+ continue;
+
+ // Pool SSA variables that are used in allocs, destroy and free or calls
+ // to functions that escaped allocs, destroys and frees respectively.
+ map<Value *, set<Instruction *> > FuncPoolAllocs, FuncPoolFrees,
+ FuncPoolDestroys;
+
+ // Traverse the function finding poolfrees and calls to functions that
+ // have poolfrees without pooldestroys on all paths in that function.
+
+ if (!F->isExternal()) {
+ // For each pool pointer def check its uses and ensure that there are
+ // no uses other than the pool_alloc, pool_free or pool_destroy calls
+
+ PA::FuncInfo* PAFI = PoolInfo->getFuncInfoOrClone(*F);
+
+ // If the function has no pool pointers (args or SSA), ignore the
+ // function.
+ if (!PAFI)
+ continue;
+
+ if (PAFI->Clone && PAFI->Clone != F)
+ continue;
+
+ if (!PAFI->PoolDescriptors.empty()) {
+ for (std::map<const DSNode*, Value*>::iterator PoolDI =
+ PAFI->PoolDescriptors.begin(), PoolDE =
+ PAFI->PoolDescriptors.end(); PoolDI != PoolDE; ++PoolDI) {
+ checkPoolSSAVarUses(F, PoolDI->second, FuncPoolAllocs,
+ FuncPoolFrees, FuncPoolDestroys);
+ FuncPoolPtrs[F].insert(PoolDI->second);
+ }
+ }
+ else
+ continue;
+
+ /*
+ if (F->getName() == "main") {
+ std::cerr << "In Function " << F->getName() << "\n";
+ printSets(FuncPoolPtrs[F], FuncPoolFrees, FuncPoolAllocs);
+ }
+ */
+
+ /*
+ // Implementing the global analysis that checks that
+ // - For each poolfree, if there is a poolallocate on another pool
+ // before a pooldestroy on any path, then this is a case 3 pool.
+ // If there is a poolallocate on the same pool before a pooldestroy
+ // on any path, then it is a case 2 pool.
+
+ // Do a local analysis on these and update the pool variables that escape
+ // the function (poolfrees without pooldestroys, poolallocs)
+ // For each instruction in the list of free/calls to free, do
+ // the following: go down to the bottom of the function looking for
+ // allocs till you see destroy. If you don't see destroy on some path,
+ // update escape list.
+ // Update escape list with allocs without destroys for arguments
+ // as well as arguments that are destroyed.
+ // TODO: Modify implementation so you are not checking that there is no
+ // alloc to other pools follows a free in the function, but to see that
+ // there is a destroy on pool between a free and an alloc to another pool
+ // Current Assumption: destroys are at the end of a function.
+ if (!FuncPoolFrees.empty()) {
+ std::cerr << "In Function " << F->getName() << "\n";
+ for (map<Value *, set<Instruction *> >::iterator ValueI =
+ FuncPoolFrees.begin(), ValueE = FuncPoolFrees.end();
+ ValueI != ValueE; ++ValueI) {
+ bool case3found = false, case2found = false;
+ for (set<Instruction *>::iterator FreeInstI =
+ (*ValueI).second.begin(),
+ FreeInstE = (*ValueI).second.end();
+ FreeInstI != FreeInstE && !case3found; ++FreeInstI) {
+ // For each free instruction or call to a function which escapes
+ // a free in pool (*ValueI).first
+ for (set<Value *>::iterator PoolPtrsI = FuncPoolPtrs[F].begin(),
+ PoolPtrsE = FuncPoolPtrs[F].end();
+ PoolPtrsI != PoolPtrsE && !case3found;
+ ++PoolPtrsI) {
+ // For each pool pointer other than the one in the free
+ // instruction under consideration, check that allocs to it
+ // don't follow the free on any path.
+ if (*PoolPtrsI != (*ValueI).first) {
+ map<Value *, set<Instruction *> >::iterator AllocSet=
+ FuncPoolAllocs.find(*PoolPtrsI);
+ if (AllocSet != FuncPoolAllocs.end())
+ for (set<Instruction *>::iterator AllocInstI =
+ (*AllocSet).second.begin(),
+ AllocInstE = (*AllocSet).second.end();
+ AllocInstI != AllocInstE && !case3found; ++AllocInstI)
+ if (followsInst(*AllocInstI, *FreeInstI, F) &&
+ *AllocInstI != *FreeInstI)
+ case3found = true;
+ } else {
+ map<Value *, set<Instruction *> >::iterator AllocSet=
+ FuncPoolAllocs.find(*PoolPtrsI);
+ if (AllocSet != FuncPoolAllocs.end())
+ for (set<Instruction *>::iterator AllocInstI =
+ (*AllocSet).second.begin(),
+ AllocInstE = (*AllocSet).second.end();
+ AllocInstI != AllocInstE && !case3found; ++AllocInstI)
+ if (followsInst(*AllocInstI, *FreeInstI, F) &&
+ *AllocInstI != *FreeInstI)
+ case2found = true;
+ }
+ }
+ }
+ if (case3found && case2found)
+ std::cerr << (*ValueI).first->getName()
+ << ": Case 2 and 3 detected\n";
+ else if (case3found)
+ std::cerr << (*ValueI).first->getName()
+ << ": Case 3 detected\n";
+ else if (case2found)
+ std::cerr << (*ValueI).first->getName()
+ << ": Case 2 detected\n";
+ else
+ std::cerr << (*ValueI).first->getName()
+ << ": Case 1 detected\n";
+ }
+ }
+ */
+
+ // Assumption: if we have pool_destroy on a pool in a function, then it
+ // is on all exit paths of the function
+ // TODO: correct later.
+ // Therefore, all pool ptr arguments that have frees but no destroys
+ // escape the function. Similarly all pool ptr arguments that have
+ // allocs but no destroys escape the function
+ for (set<Value *>::iterator PoolPtrsI = FuncPoolPtrs[F].begin(),
+ PoolPtrsE = FuncPoolPtrs[F].end(); PoolPtrsI != PoolPtrsE;
+ ++PoolPtrsI) {
+ if (isa<Argument>(*PoolPtrsI)) {
+ // Only for pool pointers that are arguments
+ if (FuncPoolFrees.find(*PoolPtrsI) != FuncPoolFrees.end() &&
+ FuncPoolFrees[*PoolPtrsI].size())
+ FuncFreedPools[F].insert(*PoolPtrsI);
+ if (FuncPoolAllocs.find(*PoolPtrsI) != FuncPoolAllocs.end() &&
+ FuncPoolAllocs[*PoolPtrsI].size())
+ FuncAllocedPools[F].insert(*PoolPtrsI);
+ if (FuncPoolDestroys.find(*PoolPtrsI) != FuncPoolDestroys.end() &&
+ FuncPoolDestroys[*PoolPtrsI].size()) {
+ FuncDestroyedPools[F].insert(*PoolPtrsI);
+ }
+ }
+ }
+
+ // TODO
+ // For each function, check that the frees in the function are case 1
+ // i.e. there are no mallocs between the free and its corresponding
+ // pool_destroy and then remove the pool free call.
+ }
+ }
+
+ // Now, traverse the call graph top-down, updating information about pool
+ // pointers that may be collapsed and inserting runtime checks
+ ReversePostOrderTraversal<CallGraph*> RPOT(&CG);
+ for (ReversePostOrderTraversal<CallGraph*>::rpo_iterator CGI = RPOT.begin(),
+ CGE = RPOT.end(); CGI != CGE; ++CGI) {
+ Function *F = (*CGI)->getFunction();
+
+ if (!F)
+ continue;
+
+ // Ignore nodes representing external functions in the call graph
+ if (!F->isExternal()) {
+ // For each pool pointer def check its uses and ensure that there are
+ // no uses other than the pool_alloc, pool_free or pool_destroy calls
+
+ PA::FuncInfo* PAFI = PoolInfo->getFuncInfoOrClone(*F);
+
+ if (!PAFI)
+ continue;
+
+ if (PAFI->Clone && PAFI->Clone != F)
+ continue;
+
+ Function *Forig;
+ if (PAFI->Clone) {
+ for(Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
+ if (PoolInfo->getFuncInfo(*MI))
+ if (PoolInfo->getFuncInfo(*MI) == PAFI) {
+ Forig = &*MI;
+ break;
+ }
+ } else
+ Forig = F;
+
+ if (FuncPoolPtrs.count(F)) {
+ for (set<Value *>::iterator PDI = FuncPoolPtrs[F].begin(),
+ PDE = FuncPoolPtrs[F].end(); PDI != PDE; ++PDI) {
+ if (isa<Argument>(*PDI)) {
+ if (CollapsedPoolPtrs[F].find(*PDI) != CollapsedPoolPtrs[F].end())
+ propagateCollapsedInfo(F, *PDI);
+ } else {
+ // This pool is poolinit'ed in this function or is a global pool
+ const DSNode *PDINode;
+
+ for (std::map<const DSNode*, Value*>::iterator PDMI =
+ PAFI->PoolDescriptors.begin(),
+ PDME = PAFI->PoolDescriptors.end(); PDMI != PDME; ++PDMI)
+ if (PDMI->second == *PDI) {
+ PDINode = PDMI->first;
+ break;
+ }
+
+ if (PDINode->isNodeCompletelyFolded()) {
+ CollapsedPoolPtrs[F].insert(*PDI);
+
+ for (unsigned i = 0 ; i < PDINode->getNumLinks(); ++i)
+ if (PDINode->getLink(i).getNode())
+ if (!PDINode->getLink(i).getNode()->isNodeCompletelyFolded()) {
+ //Collapsed to non-collapsed, so insert a check
+ insertNonCollapsedChecks(Forig, F, PDINode->getLink(i).getNode());
+ // abort();
+ break;
+ }
+
+ // Propagate this information to all the callees only if this
+ // is not a global pool
+ if (!isa<GlobalVariable>(*PDI))
+ propagateCollapsedInfo(F, *PDI);
+ }
+ }
+
+ }
+ // At this point, we know all the collapsed pools in this function
+ // Add run-time checks before all stores to pointers pointing to
+ // collapsed pools
+ addRuntimeChecks(F, Forig);
+ }
+ }
+ }
+ return moduleChanged;
+
+}
+}
+Pass *createEmbeCFreeRemovalPass() { return new EmbeCFreeRemoval(); }
+#endif
+
diff --git a/safecode/lib/PointerChecks/Makefile b/safecode/lib/PointerChecks/Makefile
new file mode 100755
index 0000000..d23e785
--- /dev/null
+++ b/safecode/lib/PointerChecks/Makefile
@@ -0,0 +1,7 @@
+LEVEL = ../../
+
+LIBRARYNAME = pointerchecks
+SHARED_LIBRARY=1
+DONT_BUILD_RELINKED=1
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/lib/StackSafety/CheckStackPointer.cpp b/safecode/lib/StackSafety/CheckStackPointer.cpp
new file mode 100755
index 0000000..67b07fd
--- /dev/null
+++ b/safecode/lib/StackSafety/CheckStackPointer.cpp
@@ -0,0 +1,108 @@
+//===-- StackSafety.cpp - Analysis for ensuring stack safety ------------//
+// Implementation of StackSafety.h
+//
+
+
+#include "llvm/Module.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Type.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/InstIterator.h"
+#include "StackSafety.h"
+#include <iostream>
+
+using namespace llvm;
+
+using namespace CSS;
+
+RegisterPass<checkStackSafety> css("css1", "check stack safety");
+
+
+
+bool checkStackSafety::markReachableAllocas(DSNode *DSN, bool start) {
+ reachableAllocaNodes.clear();
+ return markReachableAllocasInt(DSN,start);
+}
+
+bool checkStackSafety::markReachableAllocasInt(DSNode *DSN, bool start) {
+ bool returnValue = false;
+ reachableAllocaNodes.insert(DSN);
+ if (!start && DSN->isAllocaNode()) {
+ returnValue = true;
+ AllocaNodes.push_back(DSN);
+ }
+ for (unsigned i = 0, e = DSN->getSize(); i < e; i += DS::PointerSize)
+ if (DSNode *DSNchild = DSN->getLink(i).getNode()) {
+ if (reachableAllocaNodes.find(DSNchild) != reachableAllocaNodes.end()) {
+ continue;
+ } else if (markReachableAllocasInt(DSNchild)) {
+ returnValue = returnValue || true;
+ }
+ }
+ return returnValue;
+}
+
+bool checkStackSafety::runOnModule(Module &M) {
+
+ // TDDataStructures *TDDS;
+ // TDDS = &getAnalysis<TDDataStructures>();
+ CompleteBUDataStructures *BUDS;
+ BUDS = &getAnalysis<CompleteBUDataStructures>();
+ Function *MainFunc = M.getMainFunction();
+ for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
+ Function &F = *MI;
+ if (&F != MainFunc) {
+ if (!F.isExternal()) {
+ DSGraph &BUG = BUDS->getDSGraph(F);
+
+ // check if return value is a pointers
+ if (isa<PointerType>(F.getReturnType())) {
+ //return value type is a pointer
+ for(inst_iterator ii = inst_begin(F), ie = inst_end(&F); ii != ie; ++ii) {
+ if (ReturnInst *RI = dyn_cast<ReturnInst>(&*ii)) {
+ DSNode *DSN = BUG.getNodeForValue(RI).getNode();
+ if (DSN && markReachableAllocas(DSN)) {
+ std::cerr << "Instruction : \n" << RI << "points to a stack location\n";
+ std::cerr << "In Function " << F.getName() << "\n";
+ return false;
+ }
+ }
+ }
+ }
+
+ Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end();
+ for (; AI != AE; ++AI) {
+ if (isa<PointerType>(AI->getType())) {
+ DSNode *DSN = BUG.getNodeForValue(AI).getNode();
+ if (markReachableAllocas(DSN,true)) {
+ std::cerr << "Instruction : \n" << AI << "points to a stack location\n";
+ std::cerr << "In Function " << F.getName() << "\n";
+
+ }
+ }
+ }
+
+ // Also, mark allocas pointed to by globals
+ DSGraph::node_iterator DSNI = BUG.node_begin(), DSNE = BUG.node_end();
+
+ for (; DSNI != DSNE; ++DSNI) {
+ if (DSNI->isGlobalNode()) {
+ if (markReachableAllocas(DSNI)) {
+ std::cerr << "Global points to a stack location\n";
+ std::cerr << "In Function " << F.getName() << "\n";
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+
+Pass *createStackSafetyPass() { return new CSS::checkStackSafety(); }
+
+
+
diff --git a/safecode/lib/StackSafety/Makefile b/safecode/lib/StackSafety/Makefile
new file mode 100755
index 0000000..20f503b
--- /dev/null
+++ b/safecode/lib/StackSafety/Makefile
@@ -0,0 +1,7 @@
+LEVEL = ../../
+
+LIBRARYNAME = stackcheck
+SHARED_LIBRARY=1
+DONT_BUILD_RELINKED=1
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/runtime/BoundsCheckAllocator/Makefile b/safecode/runtime/BoundsCheckAllocator/Makefile
new file mode 100755
index 0000000..5803b65
--- /dev/null
+++ b/safecode/runtime/BoundsCheckAllocator/Makefile
@@ -0,0 +1,8 @@
+LEVEL = ../..
+SHARED_LIBRARY=1
+LIBRARYNAME=poolalloc_splay_rt
+
+CXXFLAGS += -fno-exceptions
+
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/runtime/BoundsCheckAllocator/PoolAllocator.cpp b/safecode/runtime/BoundsCheckAllocator/PoolAllocator.cpp
new file mode 100755
index 0000000..3b67c3b
--- /dev/null
+++ b/safecode/runtime/BoundsCheckAllocator/PoolAllocator.cpp
@@ -0,0 +1,1093 @@
+//===- PoolAllocator.cpp - Simple free-list based pool allocator ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is one possible implementation of the LLVM pool allocator runtime
+// library.
+//
+// FIXME:
+// The pointer compression functions are not thread safe.
+//===----------------------------------------------------------------------===//
+
+#include "PoolAllocator.h"
+#include "poolalloc/MMAPSupport.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+
+// Performance tweaking macros.
+#define INITIAL_SLAB_SIZE 4096
+#define LARGE_SLAB_SIZE 4096
+
+#ifndef NDEBUG
+// Configuration macros. Define up to one of these.
+#define PRINT_NUM_POOLS // Print use dynamic # pools info
+//#define PRINT_POOLDESTROY_STATS // When pools are destroyed, print stats
+//#define PRINT_POOL_TRACE // Print a full trace
+#define ENABLE_POOL_IDS // PID for access/pool traces
+
+
+// ALWAYS_USE_MALLOC_FREE - Make poolalloc/free always call malloc/free. Note
+// that if the poolfree optimization is in use that this will cause memory
+// leaks!
+//#define ALWAYS_USE_MALLOC_FREE
+#endif
+
+//===----------------------------------------------------------------------===//
+// Pool Debugging stuff.
+//===----------------------------------------------------------------------===//
+
+#if defined(ALWAYS_USE_MALLOC_FREE)
+#define DO_IF_FORCE_MALLOCFREE(x) x
+#else
+#define DO_IF_FORCE_MALLOCFREE(x)
+#endif
+
+
+#if !defined(PRINT_POOL_TRACE)
+#define DO_IF_TRACE(X)
+#else
+#define ENABLE_POOL_IDS
+#define DO_IF_TRACE(X) X
+#define PRINT_POOLDESTROY_STATS
+#endif
+
+#if defined(ENABLE_POOL_IDS)
+struct PoolID {
+ void *PD;
+ unsigned ID;
+};
+
+struct PoolID *PoolIDs = 0;
+static unsigned NumLivePools = 0;
+static unsigned NumPoolIDsAllocated = 0;
+static unsigned CurPoolID = 0;
+
+static unsigned addPoolNumber(void *PD) {
+ if (NumLivePools == NumPoolIDsAllocated) {
+ NumPoolIDsAllocated = (10+NumPoolIDsAllocated)*2;
+ PoolIDs = (PoolID*)realloc(PoolIDs, sizeof(PoolID)*NumPoolIDsAllocated);
+ }
+
+ PoolIDs[NumLivePools].PD = PD;
+ PoolIDs[NumLivePools].ID = ++CurPoolID;
+ NumLivePools++;
+ return CurPoolID;
+}
+
+static unsigned getPoolNumber(void *PD) {
+ if (PD == 0) return ~0;
+ for (unsigned i = 0; i != NumLivePools; ++i)
+ if (PoolIDs[i].PD == PD)
+ return PoolIDs[i].ID;
+ fprintf(stderr, "INVALID/UNKNOWN POOL DESCRIPTOR: 0x%lX\n",(unsigned long)PD);
+ return 0;
+}
+
+static unsigned removePoolNumber(void *PD) {
+ for (unsigned i = 0; i != NumLivePools; ++i)
+ if (PoolIDs[i].PD == PD) {
+ unsigned PN = PoolIDs[i].ID;
+ memmove(&PoolIDs[i], &PoolIDs[i+1], sizeof(PoolID)*(NumLivePools-i-1));
+ --NumLivePools;
+ return PN;
+ }
+ fprintf(stderr, "INVALID/UNKNOWN POOL DESCRIPTOR: 0x%lX\n",(unsigned long)PD);
+ return 0;
+}
+
+static void PrintPoolStats(void *Pool);
+template<typename PoolTraits>
+static void PrintLivePoolInfo() {
+ for (unsigned i = 0; i != NumLivePools; ++i) {
+ fprintf(stderr, "[%d] pool at exit ", PoolIDs[i].ID);
+ PrintPoolStats((PoolTy<PoolTraits>*)PoolIDs[i].PD);
+ }
+}
+#endif
+
+#ifdef PRINT_POOLDESTROY_STATS
+#define DO_IF_POOLDESTROY_STATS(X) X
+#define PRINT_NUM_POOLS
+
+template<typename PoolTraits>
+static void PrintPoolStats(PoolTy<PoolTraits> *Pool) {
+ fprintf(stderr,
+ "(0x%X) BytesAlloc=%d NumObjs=%d"
+ " AvgObjSize=%d NextAllocSize=%d DeclaredSize=%d\n",
+ Pool, Pool->BytesAllocated, Pool->NumObjects,
+ Pool->NumObjects ? Pool->BytesAllocated/Pool->NumObjects : 0,
+ Pool->AllocSize, Pool->DeclaredSize);
+}
+
+#else
+#define DO_IF_POOLDESTROY_STATS(X)
+#endif
+
+#ifdef PRINT_NUM_POOLS
+static unsigned PoolCounter = 0;
+static unsigned PoolsInited = 0;
+
+// MaxHeapSize - The maximum size of the heap ever.
+static unsigned MaxHeapSize = 0;
+
+// CurHeapSize - The current size of the heap.
+static unsigned CurHeapSize = 0;
+
+template<typename PoolTraits>
+static void PoolCountPrinter() {
+ DO_IF_TRACE(PrintLivePoolInfo<PoolTraits>());
+ fprintf(stderr, "\n\n"
+ "*** %d DYNAMIC POOLS INITIALIZED ***\n\n"
+ "*** %d DYNAMIC POOLS ALLOCATED FROM ***\n\n",
+ PoolsInited, PoolCounter);
+ fprintf(stderr, "MaxHeapSize = %fKB HeapSizeAtExit = %fKB "
+ "NOTE: only valid if using Heuristic=AllPools and no "
+ "bumpptr/realloc!\n", MaxHeapSize/1024.0, CurHeapSize/1024.0);
+}
+
+template<typename PoolTraits>
+static void InitPrintNumPools() {
+ static bool Initialized = 0;
+ if (!Initialized) {
+ Initialized = 1;
+ atexit(PoolCountPrinter<PoolTraits>);
+ }
+}
+
+#define DO_IF_PNP(X) X
+#else
+#define DO_IF_PNP(X)
+#endif
+
+//===----------------------------------------------------------------------===//
+// PoolSlab implementation
+//===----------------------------------------------------------------------===//
+
+
+template<typename PoolTraits>
+static void AddNodeToFreeList(PoolTy<PoolTraits> *Pool,
+ FreedNodeHeader<PoolTraits> *FreeNode) {
+ typename PoolTraits::FreeNodeHeaderPtrTy *FreeList;
+ if (FreeNode->Header.Size == Pool->DeclaredSize)
+ FreeList = &Pool->ObjFreeList;
+ else
+ FreeList = &Pool->OtherFreeList;
+
+ void *PoolBase = Pool->Slabs;
+
+ typename PoolTraits::FreeNodeHeaderPtrTy FreeNodeIdx =
+ PoolTraits::FNHPtrToIndex(FreeNode, PoolBase);
+
+ FreeNode->Prev = 0; // First on the list.
+ FreeNode->Next = *FreeList;
+ *FreeList = FreeNodeIdx;
+ if (FreeNode->Next)
+ PoolTraits::IndexToFNHPtr(FreeNode->Next, PoolBase)->Prev = FreeNodeIdx;
+}
+
+template<typename PoolTraits>
+static void UnlinkFreeNode(PoolTy<PoolTraits> *Pool,
+ FreedNodeHeader<PoolTraits> *FNH) {
+ void *PoolBase = Pool->Slabs;
+
+ // Make the predecessor point to our next node.
+ if (FNH->Prev)
+ PoolTraits::IndexToFNHPtr(FNH->Prev, PoolBase)->Next = FNH->Next;
+ else {
+ typename PoolTraits::FreeNodeHeaderPtrTy NodeIdx =
+ PoolTraits::FNHPtrToIndex(FNH, PoolBase);
+
+ if (Pool->ObjFreeList == NodeIdx)
+ Pool->ObjFreeList = FNH->Next;
+ else {
+ assert(Pool->OtherFreeList == NodeIdx &&
+ "Prev Ptr is null but not at head of free list?");
+ Pool->OtherFreeList = FNH->Next;
+ }
+ }
+
+ if (FNH->Next)
+ PoolTraits::IndexToFNHPtr(FNH->Next, PoolBase)->Prev = FNH->Prev;
+}
+
+
+// PoolSlab Structure - Hold multiple objects of the current node type.
+// Invariants: FirstUnused <= UsedEnd
+//
+template<typename PoolTraits>
+struct PoolSlab {
+ // Next - This link is used when we need to traverse the list of slabs in a
+ // pool, for example, to destroy them all.
+ PoolSlab<PoolTraits> *Next;
+
+public:
+ static void create(PoolTy<PoolTraits> *Pool, unsigned SizeHint);
+ static void *create_for_bp(PoolTy<PoolTraits> *Pool);
+ static void create_for_ptrcomp(PoolTy<PoolTraits> *Pool,
+ void *Mem, unsigned Size);
+ void destroy();
+
+ PoolSlab<PoolTraits> *getNext() const { return Next; }
+};
+
+// create - Create a new (empty) slab and add it to the end of the Pools list.
+template<typename PoolTraits>
+void PoolSlab<PoolTraits>::create(PoolTy<PoolTraits> *Pool, unsigned SizeHint) {
+ if (Pool->DeclaredSize == 0) {
+ unsigned Align = Pool->Alignment;
+ if (SizeHint < sizeof(FreedNodeHeader<PoolTraits>) -
+ sizeof(NodeHeader<PoolTraits>))
+ SizeHint = sizeof(FreedNodeHeader<PoolTraits>) -
+ sizeof(NodeHeader<PoolTraits>);
+ SizeHint = SizeHint+sizeof(FreedNodeHeader<PoolTraits>)+(Align-1);
+ SizeHint = (SizeHint & ~(Align-1))-sizeof(FreedNodeHeader<PoolTraits>);
+ // Pool->DeclaredSize = SizeHint;
+ }
+
+ unsigned Size = Pool->AllocSize;
+ Pool->AllocSize <<= 1;
+ Size = (Size+SizeHint-1) / SizeHint * SizeHint;
+ PoolSlab *PS = (PoolSlab*)malloc(Size+sizeof(PoolSlab<PoolTraits>) +
+ sizeof(NodeHeader<PoolTraits>) +
+ sizeof(FreedNodeHeader<PoolTraits>));
+ char *PoolBody = (char*)(PS+1);
+
+ // If the Alignment is greater than the size of the FreedNodeHeader, skip over
+ // some space so that the a "free pointer + sizeof(FreedNodeHeader)" is always
+ // aligned.
+ unsigned Alignment = Pool->Alignment;
+ if (Alignment > sizeof(FreedNodeHeader<PoolTraits>)) {
+ PoolBody += Alignment-sizeof(FreedNodeHeader<PoolTraits>);
+ Size -= Alignment-sizeof(FreedNodeHeader<PoolTraits>);
+ }
+
+ // Add the body of the slab to the free list.
+ FreedNodeHeader<PoolTraits> *SlabBody =(FreedNodeHeader<PoolTraits>*)PoolBody;
+ SlabBody->Header.Size = Size;
+ AddNodeToFreeList(Pool, SlabBody);
+
+ // Make sure to add a marker at the end of the slab to prevent the coallescer
+ // from trying to merge off the end of the page.
+ FreedNodeHeader<PoolTraits> *End =
+ (FreedNodeHeader<PoolTraits>*)(PoolBody + sizeof(NodeHeader<PoolTraits>)+
+ Size);
+ End->Header.Size = ~0; // Looks like an allocated chunk
+
+ // Add the slab to the list...
+ PS->Next = Pool->Slabs;
+ Pool->Slabs = PS;
+}
+
+/// create_for_bp - This creates a slab for a bump-pointer pool.
+template<typename PoolTraits>
+void *PoolSlab<PoolTraits>::create_for_bp(PoolTy<PoolTraits> *Pool) {
+ unsigned Size = Pool->AllocSize;
+ Pool->AllocSize <<= 1;
+ PoolSlab *PS = (PoolSlab*)malloc(Size+sizeof(PoolSlab));
+ char *PoolBody = (char*)(PS+1);
+ if (sizeof(PoolSlab) == 4)
+ PoolBody += 4; // No reason to start out unaligned.
+
+ // Update the end pointer.
+ Pool->OtherFreeList = (FreedNodeHeader<PoolTraits>*)((char*)(PS+1)+Size);
+
+ // Add the slab to the list...
+ PS->Next = Pool->Slabs;
+ Pool->Slabs = PS;
+ return PoolBody;
+}
+
+/// create_for_ptrcomp - Initialize a chunk of memory 'Mem' of size 'Size' for
+/// pointer compression.
+template<typename PoolTraits>
+void PoolSlab<PoolTraits>::create_for_ptrcomp(PoolTy<PoolTraits> *Pool,
+ void *SMem, unsigned Size) {
+ if (Pool->DeclaredSize == 0) {
+ unsigned Align = Pool->Alignment;
+ unsigned SizeHint = sizeof(FreedNodeHeader<PoolTraits>) -
+ sizeof(NodeHeader<PoolTraits>);
+ SizeHint = SizeHint+sizeof(FreedNodeHeader<PoolTraits>)+(Align-1);
+ SizeHint = (SizeHint & ~(Align-1))-sizeof(FreedNodeHeader<PoolTraits>);
+ Pool->DeclaredSize = SizeHint;
+ }
+
+ Size -= sizeof(PoolSlab) + sizeof(NodeHeader<PoolTraits>) +
+ sizeof(FreedNodeHeader<PoolTraits>);
+ PoolSlab *PS = (PoolSlab*)SMem;
+ char *PoolBody = (char*)(PS+1);
+
+ // If the Alignment is greater than the size of the NodeHeader, skip over some
+ // space so that the a "free pointer + sizeof(NodeHeader)" is always aligned
+ // for user data.
+ unsigned Alignment = Pool->Alignment;
+ if (Alignment > sizeof(NodeHeader<PoolTraits>)) {
+ PoolBody += Alignment-sizeof(NodeHeader<PoolTraits>);
+ Size -= Alignment-sizeof(NodeHeader<PoolTraits>);
+ }
+
+ // Add the body of the slab to the free list.
+ FreedNodeHeader<PoolTraits> *SlabBody =(FreedNodeHeader<PoolTraits>*)PoolBody;
+ SlabBody->Header.Size = Size;
+ AddNodeToFreeList(Pool, SlabBody);
+
+ // Make sure to add a marker at the end of the slab to prevent the coallescer
+ // from trying to merge off the end of the page.
+ FreedNodeHeader<PoolTraits> *End =
+ (FreedNodeHeader<PoolTraits>*)(PoolBody + sizeof(NodeHeader<PoolTraits>) +
+ Size);
+ End->Header.Size = ~0; // Looks like an allocated chunk
+ PS->Next = 0;
+}
+
+
+template<typename PoolTraits>
+void PoolSlab<PoolTraits>::destroy() {
+ free(this);
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Bump-pointer pool allocator library implementation
+//
+//===----------------------------------------------------------------------===//
+
+void poolinit_bp(PoolTy<NormalPoolTraits> *Pool, unsigned ObjAlignment) {
+ DO_IF_PNP(memset(Pool, 0, sizeof(PoolTy<NormalPoolTraits>)));
+ Pool->Slabs = 0;
+ if (ObjAlignment < 4) ObjAlignment = __alignof(double);
+ Pool->AllocSize = INITIAL_SLAB_SIZE;
+ Pool->Alignment = ObjAlignment;
+ Pool->LargeArrays = 0;
+ Pool->ObjFreeList = 0; // This is our bump pointer.
+ Pool->OtherFreeList = 0; // This is our end pointer.
+
+ unsigned PID;
+#ifdef ENABLE_POOL_IDS
+ PID = addPoolNumber(Pool);
+#endif
+
+ DO_IF_TRACE(fprintf(stderr, "[%d] poolinit_bp(0x%X, %d)\n",
+ PID, Pool, ObjAlignment));
+ DO_IF_PNP(++PoolsInited); // Track # pools initialized
+ DO_IF_PNP(InitPrintNumPools<NormalPoolTraits>());
+}
+
+void *poolalloc_bp(PoolTy<NormalPoolTraits> *Pool, unsigned NumBytes) {
+ DO_IF_FORCE_MALLOCFREE(return malloc(NumBytes));
+ assert(Pool && "Bump pointer pool does not support null PD!");
+ DO_IF_TRACE(fprintf(stderr, "[%d] poolalloc_bp(%d) -> ",
+ getPoolNumber(Pool), NumBytes));
+ DO_IF_PNP(if (Pool->NumObjects == 0) ++PoolCounter); // Track # pools.
+
+ if (NumBytes >= LARGE_SLAB_SIZE)
+ goto LargeObject;
+
+ DO_IF_PNP(++Pool->NumObjects);
+ DO_IF_PNP(Pool->BytesAllocated += NumBytes);
+
+ if (NumBytes < 1) NumBytes = 1;
+
+ uintptr_t Alignment;
+ char *BumpPtr, *EndPtr;
+ Alignment = Pool->Alignment-1;
+ BumpPtr = (char*)Pool->ObjFreeList; // Get our bump pointer.
+ EndPtr = (char*)Pool->OtherFreeList; // Get our end pointer.
+
+TryAgain:
+ // Align the bump pointer to the required boundary.
+ BumpPtr = (char*)(intptr_t((BumpPtr+Alignment)) & ~Alignment);
+
+ if (BumpPtr + NumBytes < EndPtr) {
+ void *Result = BumpPtr;
+ // Update bump ptr.
+ Pool->ObjFreeList = (FreedNodeHeader<NormalPoolTraits>*)(BumpPtr+NumBytes);
+ DO_IF_TRACE(fprintf(stderr, "%p\n", Result));
+ return Result;
+ }
+
+ BumpPtr = (char*)PoolSlab<NormalPoolTraits>::create_for_bp(Pool);
+ EndPtr = (char*)Pool->OtherFreeList; // Get our updated end pointer.
+ goto TryAgain;
+
+LargeObject:
+ // Otherwise, the allocation is a large array. Since we're not going to be
+ // able to help much for this allocation, simply pass it on to malloc.
+ LargeArrayHeader *LAH = (LargeArrayHeader*)malloc(sizeof(LargeArrayHeader) +
+ NumBytes);
+ LAH->Size = NumBytes;
+ LAH->Marker = ~0U;
+ LAH->LinkIntoList(&Pool->LargeArrays);
+ DO_IF_TRACE(fprintf(stderr, "%p [large]\n", LAH+1));
+ return LAH+1;
+}
+
+void pooldestroy_bp(PoolTy<NormalPoolTraits> *Pool) {
+ assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+
+ unsigned PID;
+#ifdef ENABLE_POOL_IDS
+ PID = removePoolNumber(Pool);
+#endif
+ DO_IF_TRACE(fprintf(stderr, "[%d] pooldestroy_bp", PID));
+ DO_IF_POOLDESTROY_STATS(PrintPoolStats(Pool));
+
+ // Free all allocated slabs.
+ PoolSlab<NormalPoolTraits> *PS = Pool->Slabs;
+ while (PS) {
+ PoolSlab<NormalPoolTraits> *Next = PS->getNext();
+ PS->destroy();
+ PS = Next;
+ }
+
+ // Free all of the large arrays.
+ LargeArrayHeader *LAH = Pool->LargeArrays;
+ while (LAH) {
+ LargeArrayHeader *Next = LAH->Next;
+ free(LAH);
+ LAH = Next;
+ }
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//
+// Pool allocator library implementation
+//
+//===----------------------------------------------------------------------===//
+
+// poolinit - Initialize a pool descriptor to empty
+//
+template<typename PoolTraits>
+static void poolinit_internal(PoolTy<PoolTraits> *Pool,
+ unsigned DeclaredSize, unsigned ObjAlignment) {
+ assert(Pool && "Null pool pointer passed into poolinit!\n");
+ memset(Pool, 0, sizeof(PoolTy<PoolTraits>));
+ Pool->splay = new_splay();
+ Pool->AllocSize = INITIAL_SLAB_SIZE;
+
+ if (ObjAlignment < 4) ObjAlignment = __alignof(double);
+ Pool->Alignment = ObjAlignment;
+
+ // Round the declared size up to an alignment boundary-header size, just like
+ // we have to do for objects.
+ if (DeclaredSize) {
+ if (DeclaredSize < sizeof(FreedNodeHeader<PoolTraits>) -
+ sizeof(NodeHeader<PoolTraits>))
+ DeclaredSize = sizeof(FreedNodeHeader<PoolTraits>) -
+ sizeof(NodeHeader<PoolTraits>);
+ DeclaredSize = DeclaredSize+sizeof(FreedNodeHeader<PoolTraits>) +
+ (ObjAlignment-1);
+ DeclaredSize = (DeclaredSize & ~(ObjAlignment-1)) -
+ sizeof(FreedNodeHeader<PoolTraits>);
+ }
+
+ Pool->DeclaredSize = DeclaredSize;
+
+ unsigned PID;
+#ifdef ENABLE_POOL_IDS
+ PID = addPoolNumber(Pool);
+#endif
+ DO_IF_TRACE(fprintf(stderr, "[%d] poolinit%s(0x%X, %d, %d)\n",
+ PID, PoolTraits::getSuffix(),
+ Pool, DeclaredSize, ObjAlignment));
+ DO_IF_PNP(++PoolsInited); // Track # pools initialized
+ DO_IF_PNP(InitPrintNumPools<PoolTraits>());
+}
+
+void poolinit(PoolTy<NormalPoolTraits> *Pool,
+ unsigned DeclaredSize, unsigned ObjAlignment) {
+ poolinit_internal(Pool, DeclaredSize, ObjAlignment);
+}
+
+// pooldestroy - Release all memory allocated for a pool
+//
+void pooldestroy(PoolTy<NormalPoolTraits> *Pool) {
+ assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+ free_splay(Pool->splay);
+ unsigned PID;
+#ifdef ENABLE_POOL_IDS
+ PID = removePoolNumber(Pool);
+#endif
+ DO_IF_TRACE(fprintf(stderr, "[%d] pooldestroy", PID));
+ DO_IF_POOLDESTROY_STATS(PrintPoolStats(Pool));
+
+ // Free all allocated slabs.
+ PoolSlab<NormalPoolTraits> *PS = Pool->Slabs;
+ while (PS) {
+ PoolSlab<NormalPoolTraits> *Next = PS->getNext();
+ PS->destroy();
+ PS = Next;
+ }
+
+ // Free all of the large arrays.
+ LargeArrayHeader *LAH = Pool->LargeArrays;
+ while (LAH) {
+ LargeArrayHeader *Next = LAH->Next;
+ free(LAH);
+ LAH = Next;
+ }
+}
+
+template<typename PoolTraits>
+static void *poolalloc_internal(PoolTy<PoolTraits> *Pool, unsigned NumBytes) {
+ DO_IF_TRACE(fprintf(stderr, "[%d] poolalloc%s(%d) -> ",
+ getPoolNumber(Pool), PoolTraits::getSuffix(), NumBytes));
+
+ // If a null pool descriptor is passed in, this is not a pool allocated data
+ // structure. Hand off to the system malloc.
+ if (Pool == 0) {
+ // std::cerr << "Null descriptor is passed in ";
+ abort();
+ void *Result = malloc(NumBytes);
+ DO_IF_TRACE(fprintf(stderr, "0x%X [malloc]\n", Result));
+ return Result;
+ }
+ DO_IF_PNP(if (Pool->NumObjects == 0) ++PoolCounter); // Track # pools.
+
+ // Objects must be at least 8 bytes to hold the FreedNodeHeader object when
+ // they are freed. This also handles allocations of 0 bytes.
+ if (NumBytes < (sizeof(FreedNodeHeader<PoolTraits>) -
+ sizeof(NodeHeader<PoolTraits>)))
+ NumBytes = sizeof(FreedNodeHeader<PoolTraits>) -
+ sizeof(NodeHeader<PoolTraits>);
+
+ // Adjust the size so that memory allocated from the pool is always on the
+ // proper alignment boundary.
+ unsigned Alignment = Pool->Alignment;
+ NumBytes = NumBytes+sizeof(FreedNodeHeader<PoolTraits>) +
+ (Alignment-1); // Round up
+ NumBytes = (NumBytes & ~(Alignment-1)) -
+ sizeof(FreedNodeHeader<PoolTraits>); // Truncate
+
+ DO_IF_PNP(CurHeapSize += (NumBytes + sizeof(NodeHeader<PoolTraits>)));
+ DO_IF_PNP(if (CurHeapSize > MaxHeapSize) MaxHeapSize = CurHeapSize);
+
+ DO_IF_PNP(++Pool->NumObjects);
+ DO_IF_PNP(Pool->BytesAllocated += NumBytes);
+
+ // Fast path - allocate objects off the object list.
+ if (NumBytes == Pool->DeclaredSize && Pool->ObjFreeList != 0) {
+ typename PoolTraits::FreeNodeHeaderPtrTy NodeIdx = Pool->ObjFreeList;
+ void *PoolBase = Pool->Slabs;
+ FreedNodeHeader<PoolTraits> *Node =
+ PoolTraits::IndexToFNHPtr(NodeIdx, PoolBase);
+ UnlinkFreeNode(Pool, Node);
+ assert(NumBytes == Node->Header.Size);
+
+ Node->Header.Size = NumBytes|1; // Mark as allocated
+ //store it in the splay tree
+ if (NumBytes != Pool->DeclaredSize)
+ splay_insert_ptr(Pool->splay, (unsigned long)(&Node->Header+1), NumBytes);
+ DO_IF_TRACE(fprintf(stderr, "0x%X\n", &Node->Header+1));
+ return &Node->Header+1;
+ }
+
+ if (PoolTraits::UseLargeArrayObjects &&
+ NumBytes >= LARGE_SLAB_SIZE-sizeof(PoolSlab<PoolTraits>) -
+ sizeof(NodeHeader<PoolTraits>))
+ goto LargeObject;
+
+ // Fast path. In the common case, we can allocate a portion of the node at
+ // the front of the free list.
+ do {
+ void *PoolBase = Pool->Slabs;
+ FreedNodeHeader<PoolTraits> *FirstNode =
+ PoolTraits::IndexToFNHPtr(Pool->OtherFreeList, PoolBase);
+ if (FirstNode) {
+ unsigned FirstNodeSize = FirstNode->Header.Size;
+ if (FirstNodeSize >= NumBytes) {
+ if (FirstNodeSize >= 2*NumBytes+sizeof(NodeHeader<PoolTraits>)) {
+ // Put the remainder back on the list...
+ FreedNodeHeader<PoolTraits> *NextNodes =
+ (FreedNodeHeader<PoolTraits>*)((char*)FirstNode +
+ sizeof(NodeHeader<PoolTraits>) +NumBytes);
+
+ // Remove from list
+ UnlinkFreeNode(Pool, FirstNode);
+
+ NextNodes->Header.Size = FirstNodeSize-NumBytes -
+ sizeof(NodeHeader<PoolTraits>);
+ AddNodeToFreeList(Pool, NextNodes);
+
+ } else {
+ UnlinkFreeNode(Pool, FirstNode);
+ NumBytes = FirstNodeSize;
+ }
+ FirstNode->Header.Size = NumBytes|1; // Mark as allocated
+ DO_IF_TRACE(fprintf(stderr, "0x%X\n", &FirstNode->Header+1));
+ //Store it in the splay tree....
+ // Pool->splay =
+ if (NumBytes != Pool->DeclaredSize)
+ splay_insert_ptr(Pool->splay, (unsigned long) (&FirstNode->Header+1), NumBytes);
+ return &FirstNode->Header+1;
+ }
+
+ // Perform a search of the free list, taking the front of the first free
+ // chunk that is big enough.
+ typename PoolTraits::FreeNodeHeaderPtrTy *FN = &Pool->OtherFreeList;
+ FreedNodeHeader<PoolTraits> *FNN = FirstNode;
+
+ // Search the list for the first-fit.
+ while (FNN && FNN->Header.Size < NumBytes) {
+ // Advance FN to point to the Next field of FNN.
+ FN = &FNN->Next;
+
+ // Advance FNN to point to whatever the next node points to (null or the
+ // next node in the free list).
+ FNN = PoolTraits::IndexToFNHPtr(*FN, PoolBase);
+ }
+
+ if (FNN) {
+ // We found a slab big enough. If it's a perfect fit, just unlink
+ // from the free list, otherwise, slice a little bit off and adjust
+ // the free list.
+ if (FNN->Header.Size > 2*NumBytes+sizeof(NodeHeader<PoolTraits>)) {
+ UnlinkFreeNode(Pool, FNN);
+
+ // Put the remainder back on the list...
+ FreedNodeHeader<PoolTraits> *NextNodes =
+ (FreedNodeHeader<PoolTraits>*)((char*)FNN +
+ sizeof(NodeHeader<PoolTraits>) +
+ NumBytes);
+ NextNodes->Header.Size = FNN->Header.Size-NumBytes -
+ sizeof(NodeHeader<PoolTraits>);
+ AddNodeToFreeList(Pool, NextNodes);
+ } else {
+ UnlinkFreeNode(Pool, FNN);
+ NumBytes = FNN->Header.Size;
+ }
+ FNN->Header.Size = NumBytes|1; // Mark as allocated
+ DO_IF_TRACE(fprintf(stderr, "0x%X\n", &FNN->Header+1));
+ //Store it in the splay tree....
+ // Pool->splay =
+ if (NumBytes != Pool->DeclaredSize)
+ splay_insert_ptr(Pool->splay, (unsigned long) (&FNN->Header+1), NumBytes);
+ return &FNN->Header+1;
+ }
+ }
+
+ // If we are not allowed to grow this pool, don't.
+ if (!PoolTraits::CanGrowPool) {
+ abort();
+ return 0;
+ }
+
+ // Oops, we didn't find anything on the free list big enough! Allocate
+ // another slab and try again.
+ PoolSlab<PoolTraits>::create(Pool, NumBytes);
+ } while (1);
+
+LargeObject:
+ // Otherwise, the allocation is a large array. Since we're not going to be
+ // able to help much for this allocation, simply pass it on to malloc.
+ LargeArrayHeader *LAH = (LargeArrayHeader*)malloc(sizeof(LargeArrayHeader) +
+ NumBytes);
+ LAH->Size = NumBytes;
+ LAH->Marker = ~0U;
+ LAH->LinkIntoList(&Pool->LargeArrays);
+ DO_IF_TRACE(fprintf(stderr, "0x%X [large]\n", LAH+1));
+ //Store it in the splay tree....
+ //Pool->splay =
+ if (NumBytes != Pool->DeclaredSize)
+ splay_insert_ptr(Pool->splay, (unsigned long) (LAH+1), NumBytes);
+ return LAH+1;
+}
+
+template<typename PoolTraits>
+static void poolfree_internal(PoolTy<PoolTraits> *Pool, void *Node) {
+ if (Node == 0) return;
+ DO_IF_TRACE(fprintf(stderr, "[%d] poolfree%s(%p) ",
+ getPoolNumber(Pool), PoolTraits::getSuffix(), Node));
+
+ // If a null pool descriptor is passed in, this is not a pool allocated data
+ // structure. Hand off to the system free.
+ if (Pool == 0) {
+ abort();
+ free(Node);
+ DO_IF_TRACE(fprintf(stderr, "[free]\n"));
+ return;
+ }
+ Splay *splay = splay_find_ptr(Pool->splay, (unsigned long)Node);
+ splay_delete_node(splay);
+ // Check to see how many elements were allocated to this node...
+ FreedNodeHeader<PoolTraits> *FNH =
+ (FreedNodeHeader<PoolTraits>*)((char*)Node-sizeof(NodeHeader<PoolTraits>));
+ assert((FNH->Header.Size & 1) && "Node not allocated!");
+ unsigned Size = FNH->Header.Size & ~1;
+
+ if (Size == ~1U) goto LargeArrayCase;
+ DO_IF_TRACE(fprintf(stderr, "%d bytes\n", Size));
+
+ DO_IF_PNP(CurHeapSize -= (Size + sizeof(NodeHeader<PoolTraits>)));
+
+ // If the node immediately after this one is also free, merge it into node.
+ FreedNodeHeader<PoolTraits> *NextFNH;
+ NextFNH = (FreedNodeHeader<PoolTraits>*)((char*)Node+Size);
+ while ((NextFNH->Header.Size & 1) == 0) {
+ // Unlink NextFNH from the freelist that it is in.
+ UnlinkFreeNode(Pool, NextFNH);
+ Size += sizeof(NodeHeader<PoolTraits>)+NextFNH->Header.Size;
+ NextFNH = (FreedNodeHeader<PoolTraits>*)((char*)Node+Size);
+ }
+
+ // If there are already nodes on the freelist, see if these blocks can be
+ // coallesced into one of the early blocks on the front of the list. This is
+ // a simple check that prevents many horrible forms of fragmentation,
+ // particularly when freeing objects in allocation order.
+ //
+ if (Pool->ObjFreeList) {
+ void *PoolBase = Pool->Slabs;
+ FreedNodeHeader<PoolTraits> *ObjFNH =
+ PoolTraits::IndexToFNHPtr(Pool->ObjFreeList, PoolBase);
+
+ if ((char*)ObjFNH + sizeof(NodeHeader<PoolTraits>) +
+ ObjFNH->Header.Size == (char*)FNH) {
+ // Merge this with a node that is already on the object size free list.
+ // Because the object is growing, we will never be able to find it if we
+ // leave it on the object freelist.
+ UnlinkFreeNode(Pool, ObjFNH);
+ ObjFNH->Header.Size += Size+sizeof(NodeHeader<PoolTraits>);
+ AddNodeToFreeList(Pool, ObjFNH);
+ return;
+ }
+ }
+
+ if (Pool->OtherFreeList) {
+ void *PoolBase = Pool->Slabs;
+ FreedNodeHeader<PoolTraits> *OFNH =
+ PoolTraits::IndexToFNHPtr(Pool->OtherFreeList, PoolBase);
+
+ if ((char*)OFNH + sizeof(NodeHeader<PoolTraits>) +
+ OFNH->Header.Size == (char*)FNH) {
+ // Merge this with a node that is already on the object size free list.
+ OFNH->Header.Size += Size+sizeof(NodeHeader<PoolTraits>);
+ return;
+ }
+ }
+
+ FNH->Header.Size = Size;
+ AddNodeToFreeList(Pool, FNH);
+ return;
+
+LargeArrayCase:
+ LargeArrayHeader *LAH = ((LargeArrayHeader*)Node)-1;
+ DO_IF_TRACE(fprintf(stderr, "%d bytes [large]\n", LAH->Size));
+ DO_IF_PNP(CurHeapSize -= LAH->Size);
+
+ // Unlink it from the list of large arrays and free it.
+ LAH->UnlinkFromList();
+ free(LAH);
+}
+
+template<typename PoolTraits>
+static void *poolrealloc_internal(PoolTy<PoolTraits> *Pool, void *Node,
+ unsigned NumBytes) {
+ DO_IF_TRACE(fprintf(stderr, "[%d] poolrealloc%s(0x%X, %d) -> ",
+ getPoolNumber(Pool), PoolTraits::getSuffix(),
+ Node, NumBytes));
+
+ // If a null pool descriptor is passed in, this is not a pool allocated data
+ // structure. Hand off to the system realloc.
+ if (Pool == 0) {
+ void *Result = realloc(Node, NumBytes);
+ DO_IF_TRACE(fprintf(stderr, "0x%X (system realloc)\n", Result));
+ return Result;
+ }
+ if (Node == 0) return poolalloc(Pool, NumBytes);
+ if (NumBytes == 0) {
+ poolfree(Pool, Node);
+ DO_IF_TRACE(fprintf(stderr, "freed\n"));
+ return 0;
+ }
+
+ FreedNodeHeader<PoolTraits> *FNH =
+ (FreedNodeHeader<PoolTraits>*)((char*)Node-sizeof(NodeHeader<PoolTraits>));
+ assert((FNH->Header.Size & 1) && "Node not allocated!");
+ unsigned Size = FNH->Header.Size & ~1;
+ if (Size != ~1U) {
+ // FIXME: This is obviously much worse than it could be. In particular, we
+ // never try to expand something in a pool. This might hurt some programs!
+ void *New = poolalloc(Pool, NumBytes);
+ assert(New != 0 && "Our poolalloc doesn't ever return null for failure!");
+
+ // Copy the min of the new and old sizes over.
+ memcpy(New, Node, Size < NumBytes ? Size : NumBytes);
+ poolfree(Pool, Node);
+ DO_IF_TRACE(fprintf(stderr, "0x%X (moved)\n", New));
+ return New;
+ }
+
+ // Otherwise, we have a large array. Perform the realloc using the system
+ // realloc function. This case is actually quite common as many large blocks
+ // end up being realloc'd it seems.
+ LargeArrayHeader *LAH = ((LargeArrayHeader*)Node)-1;
+ LAH->UnlinkFromList();
+
+ LargeArrayHeader *NewLAH =
+ (LargeArrayHeader*)realloc(LAH, sizeof(LargeArrayHeader)+NumBytes);
+
+ DO_IF_TRACE(if (LAH == NewLAH)
+ fprintf(stderr, "resized in place (system realloc)\n");
+ else
+ fprintf(stderr, "0x%X (moved by system realloc)\n", NewLAH+1));
+ NewLAH->LinkIntoList(&Pool->LargeArrays);
+ return NewLAH+1;
+}
+
+unsigned poolobjsize(PoolTy<NormalPoolTraits> *Pool, void *Node) {
+ if (Node == 0) return 0;
+
+ // If a null pool descriptor is passed in, this is not a pool allocated data
+ // structure. We don't really have any way to service this!!
+ if (Pool == 0) {
+ fprintf(stderr, "ERROR: Cannot call poolobjsize on a pool that is getting"
+ " memory from the heap. Sorry!\n");
+ abort();
+ }
+
+ // Check to see how many bytes were allocated to this node.
+ FreedNodeHeader<NormalPoolTraits> *FNH =
+ (FreedNodeHeader<NormalPoolTraits>*)((char*)Node -
+ sizeof(NodeHeader<NormalPoolTraits>));
+ assert((FNH->Header.Size & 1) && "Node not allocated!");
+ unsigned Size = FNH->Header.Size & ~1;
+ if (Size != ~1U) return Size;
+
+ // Otherwise, we have a large array.
+ LargeArrayHeader *LAH = ((LargeArrayHeader*)Node)-1;
+ return LAH->Size;
+}
+
+
+void *poolalloc(PoolTy<NormalPoolTraits> *Pool, unsigned NumBytes) {
+ DO_IF_FORCE_MALLOCFREE(return malloc(NumBytes));
+ void *ret = poolalloc_internal(Pool, NumBytes);
+ // printf("Allocated in pool %x num bytes %d ret val %x\n",Pool, NumBytes, ret);
+ return ret;
+}
+
+
+void poolfree(PoolTy<NormalPoolTraits> *Pool, void *Node) {
+ DO_IF_FORCE_MALLOCFREE(free(Node); return);
+ poolfree_internal(Pool, Node);
+}
+/*
+void poolcheck(PoolTy<NormalPoolTraits> *Pool, void *referrent, void *Node) {
+ Splay *splay = splay_find_ptr(Pool->splay, (unsigned long) referrent);
+ if (((unsigned long) referrent) + splay->val < (unsigned long) Node) {
+ printf("Bounds check failure");
+ abort();
+ }
+}
+*/
+void *getreferrent(PoolTy<NormalPoolTraits> *Pool, void *referrent) {
+ return splay_find_ptr(Pool->splay, (unsigned long) referrent);
+}
+
+bool poolcheck4(Splay *splay, void *Node) {
+ if( ((unsigned long) splay->key) > ((unsigned long)Node))
+ return false;
+ if (((unsigned long) splay->key) + splay->val < (unsigned long) Node) {
+ return false;
+ };
+ return true;
+}
+
+void* poolcheckslow(PoolTy<NormalPoolTraits> *A, void *B, void *C) {
+ void *r = getreferrent(A, B);
+
+ if (turn == 1) {
+ pCache1 = r;
+ turn = 2;
+ } else {
+ pCache2 = r;
+ turn = 1;
+ }
+ if (!poolcheck4((Splay *)r, C)) {
+ printf("Bounds error \n");
+ abort();
+ }
+ return r;
+}
+
+
+
+void poolregister(PoolTy<NormalPoolTraits> *Pool, void *referrent, unsigned size) {
+ if (Pool)
+ splay_insert_ptr(Pool->splay, (unsigned long) referrent, size);
+}
+
+void *poolrealloc(PoolTy<NormalPoolTraits> *Pool, void *Node,
+ unsigned NumBytes) {
+ DO_IF_FORCE_MALLOCFREE(return realloc(Node, NumBytes));
+ return poolrealloc_internal(Pool, Node, NumBytes);
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Pointer Compression runtime library. Most of these are just wrappers
+// around the normal pool routines.
+//===----------------------------------------------------------------------===//
+
+// For now, use address space reservation of 256MB.
+#define POOLSIZE (256*1024*1024)
+
+// Pools - When we are done with a pool, don't munmap it, keep it around for
+// next time.
+static PoolSlab<CompressedPoolTraits> *Pools[4] = { 0, 0, 0, 0 };
+
+
+void *poolinit_pc(PoolTy<CompressedPoolTraits> *Pool,
+ unsigned DeclaredSize, unsigned ObjAlignment) {
+ poolinit_internal(Pool, DeclaredSize, ObjAlignment);
+
+ // The number of nodes to stagger in the mmap'ed pool
+ static unsigned stagger=0;
+
+ // Create the pool. We have to do this eagerly (instead of on the first
+ // allocation), because code may want to eagerly copy the pool base into a
+ // register.
+
+ // If we already have a pool mapped, reuse it.
+ for (unsigned i = 0; i != 4; ++i)
+ if (Pools[i]) {
+ Pool->Slabs = Pools[i];
+ Pools[i] = 0;
+ break;
+ }
+
+ //
+ // Wrap the stagger value back to zero if we're past the size of the pool.
+ // This way, we always reserve less than 2*POOLSIZE of the virtual address
+ // space.
+ //
+ if ((stagger * DeclaredSize) >= POOLSIZE)
+ stagger = 0;
+
+ if (Pool->Slabs == 0) {
+ //
+ // Didn't find an existing pool, create one.
+ //
+ // To create a pool, we stagger the beginning of the pool so that pools
+ // do not end up starting on the same page boundary (creating extra cache
+ // conflicts).
+ //
+ Pool->Slabs = (PoolSlab<CompressedPoolTraits>*)
+ AllocateSpaceWithMMAP(POOLSIZE + (DeclaredSize * stagger), true);
+ Pool->Slabs += (DeclaredSize * stagger);
+
+ // Increase the stagger amount by one node.
+ stagger++;
+ DO_IF_TRACE(fprintf(stderr, "RESERVED ADDR SPACE: %p -> %p\n",
+ Pool->Slabs, (char*)Pool->Slabs+POOLSIZE));
+ }
+ PoolSlab<CompressedPoolTraits>::create_for_ptrcomp(Pool, Pool->Slabs,
+ POOLSIZE);
+ return Pool->Slabs;
+}
+
+void pooldestroy_pc(PoolTy<CompressedPoolTraits> *Pool) {
+ assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+ if (Pool->Slabs == 0)
+ return; // no memory allocated from this pool.
+
+ unsigned PID;
+#ifdef ENABLE_POOL_IDS
+ PID = removePoolNumber(Pool);
+#endif
+ DO_IF_TRACE(fprintf(stderr, "[%d] pooldestroy_pc", PID));
+ DO_IF_POOLDESTROY_STATS(PrintPoolStats(Pool));
+
+ // If there is space to remember this pool, do so.
+ for (unsigned i = 0; i != 4; ++i)
+ if (Pools[i] == 0) {
+ Pools[i] = Pool->Slabs;
+ return;
+ }
+
+ // Otherwise, just munmap it.
+ DO_IF_TRACE(fprintf(stderr, "UNMAPPING ADDR SPACE: %p -> %p\n",
+ Pool->Slabs, (char*)Pool->Slabs+POOLSIZE));
+ munmap(Pool->Slabs, POOLSIZE);
+}
+
+unsigned long long poolalloc_pc(PoolTy<CompressedPoolTraits> *Pool,
+ unsigned NumBytes) {
+ void *Result = poolalloc_internal(Pool, NumBytes);
+ return (char*)Result-(char*)Pool->Slabs;
+}
+
+void poolfree_pc(PoolTy<CompressedPoolTraits> *Pool, unsigned long long Node) {
+ poolfree_internal(Pool, (char*)Pool->Slabs+Node);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Access Tracing Runtime Library Support
+//===----------------------------------------------------------------------===//
+
+static FILE *FD = 0;
+void poolaccesstraceinit() {
+#ifdef ALWAYS_USE_MALLOC_FREE
+ FD = fopen("trace.malloc.csv", "w");
+#else
+ FD = fopen("trace.pa.csv", "w");
+#endif
+}
+
+#define NUMLRU 2
+static void *LRUWindow[NUMLRU];
+
+void poolaccesstrace(void *Ptr, void *PD) {
+ static unsigned Time = ~0U;
+ static void *LastPtr = 0;
+
+ // Not pool memory?
+ if (PD == 0) return;
+
+ // Filter out stuff that is not to the heap.
+ ++Time;
+ if ((uintptr_t)Ptr > 1000000000UL)
+ return;
+
+ Ptr = (void*)((intptr_t)Ptr & ~31L);
+
+#if 1
+ // Drop duplicate points.
+ for (unsigned i = 0; i != NUMLRU; ++i)
+ if (Ptr == LRUWindow[i]) {
+ memmove(LRUWindow+1, LRUWindow, sizeof(void*)*i);
+ LRUWindow[0] = Ptr;
+ return;
+ }
+
+ // Rotate LRU window.
+ memmove(LRUWindow+1, LRUWindow, sizeof(void*)*(NUMLRU-1));
+ LRUWindow[0] = Ptr;
+#endif
+
+ // Delete many points to reduce data.
+ static unsigned int Ctr;
+ if ((++Ctr & 31)) return;
+
+
+ fprintf(FD, "%d", Time);
+#if defined(ENABLE_POOL_IDS)
+ for (unsigned PID = getPoolNumber(PD)+1; PID; --PID)
+ fprintf(FD,"\t?");
+#else
+ fprintf(FD, "\t%p ", PD);
+#endif
+ fprintf(FD, "\t%lu\n", (intptr_t)Ptr);
+}
diff --git a/safecode/runtime/BoundsCheckAllocator/PoolAllocator.h b/safecode/runtime/BoundsCheckAllocator/PoolAllocator.h
new file mode 100755
index 0000000..67e2a93
--- /dev/null
+++ b/safecode/runtime/BoundsCheckAllocator/PoolAllocator.h
@@ -0,0 +1,242 @@
+//===- PoolAllocator.h - Pool allocator runtime interface file --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface which is implemented by the LLVM pool
+// allocator runtime library.
+//
+// Note: this version uses splay data structure to note object sizes and
+// uses it to do bounds checking like Jones-Kelley
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POOLALLOCATOR_RUNTIME_H
+#define POOLALLOCATOR_RUNTIME_H
+
+#include <assert.h>
+#include "splay.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+template<typename PoolTraits>
+struct PoolSlab;
+template<typename PoolTraits>
+struct FreedNodeHeader;
+
+// NormalPoolTraits - This describes normal pool allocation pools, which can
+// address the entire heap, and are made out of multiple chunks of memory. The
+// object header is a full machine word, and pointers into the heap are native
+// pointers.
+struct NormalPoolTraits {
+ typedef unsigned long NodeHeaderType;
+ enum {
+ UseLargeArrayObjects = 1,
+ CanGrowPool = 1
+ };
+
+ // Pointers are just pointers.
+ typedef FreedNodeHeader<NormalPoolTraits>* FreeNodeHeaderPtrTy;
+
+ static const char *getSuffix() { return ""; }
+
+ /// DerefFNHPtr - Given an index into the pool, return a pointer to the
+ /// FreeNodeHeader object.
+ static FreedNodeHeader<NormalPoolTraits>*
+ IndexToFNHPtr(FreeNodeHeaderPtrTy P, void *PoolBase) {
+ return P;
+ }
+
+ static FreeNodeHeaderPtrTy
+ FNHPtrToIndex(FreedNodeHeader<NormalPoolTraits>* FNHP, void *PoolBase) {
+ return FNHP;
+ }
+};
+
+
+// CompressedPoolTraits - This describes a statically pointer compressed pool,
+// which is known to be <= 2^32 bytes in size (even on a 64-bit machine), and is
+// made out of a single contiguous block. The meta-data to represent the pool
+// uses 32-bit indexes from the start of the pool instead of full pointers to
+// decrease the minimum object size.
+struct CompressedPoolTraits {
+ typedef unsigned NodeHeaderType;
+
+ enum {
+ UseLargeArrayObjects = 0,
+ CanGrowPool = 0
+ };
+
+ // Represent pointers with indexes from the pool base.
+ typedef unsigned FreeNodeHeaderPtrTy;
+
+ static const char *getSuffix() { return "_pc"; }
+
+ /// DerefFNHPtr - Given an index into the pool, return a pointer to the
+ /// FreeNodeHeader object.
+ static FreedNodeHeader<CompressedPoolTraits>*
+ IndexToFNHPtr(FreeNodeHeaderPtrTy P, void *PoolBase) {
+ return (FreedNodeHeader<CompressedPoolTraits>*)((char*)PoolBase + P);
+ }
+
+ static FreeNodeHeaderPtrTy
+ FNHPtrToIndex(FreedNodeHeader<CompressedPoolTraits>* FNHP, void *PoolBase) {
+ assert(FNHP && PoolBase && "Can't handle null FHNP!");
+ return (char*)FNHP - (char*)PoolBase;
+ }
+};
+
+
+// NodeHeader - Each block of memory is preceeded in the the pool by one of
+// these headers.
+template<typename PoolTraits>
+struct NodeHeader {
+ typename PoolTraits::NodeHeaderType Size;
+};
+
+
+// When objects are on the free list, we pretend they have this header.
+template<typename PoolTraits>
+struct FreedNodeHeader {
+ // NormalHeader - This is the normal node header that is on allocated or free
+ // blocks.
+ NodeHeader<PoolTraits> Header;
+
+ // Next - The next object in the free list.
+ typename PoolTraits::FreeNodeHeaderPtrTy Next;
+
+ // Prev - The node that points to this node on the free list. This is null
+ // if it is the first node in one of the two free lists.
+ typename PoolTraits::FreeNodeHeaderPtrTy Prev;
+};
+
+
+// Large Arrays are passed on to directly malloc, and are not necessarily page
+// aligned. These arrays are marked by setting the object size preheader to ~1.
+// LargeArrays are on their own list to allow for efficient deletion.
+struct LargeArrayHeader {
+ LargeArrayHeader **Prev, *Next;
+
+ // Size - This contains the size of the object.
+ unsigned long Size;
+
+ // Marker: this is the ObjectSize marker which MUST BE THE LAST ELEMENT of
+ // this header!
+ unsigned long Marker;
+
+ void UnlinkFromList() {
+ *Prev = Next;
+ if (Next)
+ Next->Prev = Prev;
+ }
+
+ void LinkIntoList(LargeArrayHeader **List) {
+ Next = *List;
+ if (Next)
+ Next->Prev = &Next;
+ *List = this;
+ Prev = List;
+ }
+};
+
+
+template<typename PoolTraits>
+struct PoolTy {
+ // Slabs - the list of slabs in this pool. NOTE: This must remain the first
+ // memory of this structure for the pointer compression pass.
+ PoolSlab<PoolTraits> *Slabs;
+
+ // The free node lists for objects of various sizes.
+ typename PoolTraits::FreeNodeHeaderPtrTy ObjFreeList;
+ typename PoolTraits::FreeNodeHeaderPtrTy OtherFreeList;
+
+ // Alignment - The required alignment of allocations the pool in bytes.
+ unsigned Alignment;
+
+ // The declared size of the pool, just kept for the record.
+ unsigned DeclaredSize;
+
+ // LargeArrays - A doubly linked list of large array chunks, dynamically
+ // allocated with malloc.
+ LargeArrayHeader *LargeArrays;
+
+ // The size to allocate for the next slab.
+ unsigned AllocSize;
+
+ // NumObjects - the number of poolallocs for this pool.
+ unsigned NumObjects;
+
+ // BytesAllocated - The total number of bytes ever allocated from this pool.
+ // Together with NumObjects, allows us to calculate average object size.
+ unsigned BytesAllocated;
+
+ Splay *splay;
+};
+
+extern "C" {
+ void exactcheck(int a, int b) {
+ if ((0 > a) || (a >= b)) {
+ fprintf(stderr, "exact check failed\n");
+ exit(-1);
+ }
+ }
+
+ void poolinit(PoolTy<NormalPoolTraits> *Pool,
+ unsigned DeclaredSize, unsigned ObjAlignment);
+ void poolmakeunfreeable(PoolTy<NormalPoolTraits> *Pool);
+ void pooldestroy(PoolTy<NormalPoolTraits> *Pool);
+ void *poolalloc(PoolTy<NormalPoolTraits> *Pool, unsigned NumBytes);
+ void *poolrealloc(PoolTy<NormalPoolTraits> *Pool,
+ void *Node, unsigned NumBytes);
+ void *poolmemalign(PoolTy<NormalPoolTraits> *Pool,
+ unsigned Alignment, unsigned NumBytes);
+ void poolfree(PoolTy<NormalPoolTraits> *Pool, void *Node);
+ void poolregister(PoolTy<NormalPoolTraits> *Pool, void *Node, unsigned size);
+
+ /// poolobjsize - Return the size of the object at the specified address, in
+ /// the specified pool. Note that this cannot be used in normal cases, as it
+ /// is completely broken if things land in the system heap. Perhaps in the
+ /// future. :(
+ ///
+ unsigned poolobjsize(PoolTy<NormalPoolTraits> *Pool, void *Node);
+
+ // Bump pointer pool library. This is a pool implementation that does not
+ // support frees or reallocs to the pool. As such, it can be much more
+ // efficient and simpler than a general pool implementation.
+ void poolinit_bp(PoolTy<NormalPoolTraits> *Pool, unsigned ObjAlignment);
+ void *poolalloc_bp(PoolTy<NormalPoolTraits> *Pool, unsigned NumBytes);
+ void pooldestroy_bp(PoolTy<NormalPoolTraits> *Pool);
+
+
+ // Pointer Compression runtime library. Most of these are just wrappers
+ // around the normal pool routines.
+ void *poolinit_pc(PoolTy<CompressedPoolTraits> *Pool, unsigned NodeSize,
+ unsigned ObjAlignment);
+ void pooldestroy_pc(PoolTy<CompressedPoolTraits> *Pool);
+ unsigned long long poolalloc_pc(PoolTy<CompressedPoolTraits> *Pool,
+ unsigned NumBytes);
+ void poolfree_pc(PoolTy<CompressedPoolTraits> *Pool, unsigned long long Node);
+ //void *poolmemalign_pc(PoolTy *Pool, unsigned Alignment, unsigned NumBytes);
+
+
+ // Access tracing runtime library support.
+ void poolaccesstraceinit(void);
+ void poolaccesstrace(void *Ptr, void *PD);
+
+ //Dinakar for run-time bounds checking
+ void* poolcheckslow(PoolTy<NormalPoolTraits> *A, void *B, void *C);
+
+ // bool poolcheck1(Splay *splay, void *Node);
+ void *getreferrent(PoolTy<NormalPoolTraits> *Pool, void *base) __attribute__ ((const));
+ // void poolcheck(PoolTy<NormalPoolTraits> *Pool, void *Ptr, void *referrent);
+
+ extern void * pCache1, *pCache2;
+ extern int turn;
+}
+
+#endif
+
diff --git a/safecode/runtime/BoundsCheckAllocator/splay.cpp b/safecode/runtime/BoundsCheckAllocator/splay.cpp
new file mode 100755
index 0000000..21dd98c
--- /dev/null
+++ b/safecode/runtime/BoundsCheckAllocator/splay.cpp
@@ -0,0 +1,322 @@
+// Note: This file is obtained from
+// http://www.cs.utk.edu/~cs140/spring-2005/notes/Splay/
+// FIXME: This may not be the most efficient version of splay implementation
+// This may be updated with a different splay implementation in near future
+#include <stdio.h>
+#include "splay.h"
+#include <stdlib.h>
+void rotate(Splay *node)
+{
+ Splay *parent, *grandparent;
+
+ if (node->parent->is_sentinel) return;
+
+ parent = node->parent;
+ grandparent = parent->parent;
+
+ if (parent->left == node) {
+ parent->left = node->right;
+ if (parent->left != NULL) parent->left->parent = parent;
+ node->right = parent;
+ } else if (parent->right == node) {
+ parent->right = node->left;
+ if (parent->right != NULL) parent->right->parent = parent;
+ node->left = parent;
+ } else {
+ fprintf(stderr, "rotate: error: parent's children are not right\n");
+ exit(1);
+ }
+
+ parent->parent = node;
+ node->parent = grandparent;
+
+ if (grandparent->is_sentinel) {
+ grandparent->parent = node;
+ } else if (grandparent->left == parent) {
+ grandparent->left = node;
+ } else if (grandparent->right == parent) {
+ grandparent->right = node;
+ } else {
+ fprintf(stderr, "rotate: error: grandparent's children are not right\n");
+ exit(1);
+ }
+}
+
+ void splay(Splay *node)
+{
+ Splay *parent, *grandparent;
+
+ if (node->is_sentinel) return;
+
+ while(1) {
+ if (node->parent->is_sentinel) return;
+
+ parent = node->parent;
+ grandparent = parent->parent;
+
+ /* If the node's parent is the root of the tree, do one rotation */
+
+ if (grandparent->is_sentinel) {
+ rotate(node);
+
+ /* If we have a zig-zig, then rotate my parent, then rotate me */
+
+ } else if ((parent->left == node && grandparent->left == parent) ||
+ (parent->right == node && grandparent->right == parent)) {
+ rotate(parent);
+ rotate(node);
+
+ /* If we have a zig-zag, then rotate me twice */
+
+ } else {
+ rotate(node);
+ rotate(node);
+ }
+ }
+}
+
+Splay *new_splay()
+{
+ Splay *tree;
+
+ tree = (Splay *) malloc(sizeof(struct splay));
+ tree->key = 0;
+ tree->val = 0;
+ tree->is_sentinel = 1;
+ tree->flink = tree;
+ tree->blink = tree;
+ tree->left = NULL;
+ tree->right = NULL;
+ tree->parent = NULL;
+ return tree;
+}
+
+Splay *splay_root(Splay *tree)
+{
+ return tree->parent;
+}
+
+Splay *splay_first(Splay *tree)
+{
+ return tree->flink;
+}
+
+Splay *splay_last(Splay *tree)
+{
+ return tree->blink;
+}
+
+Splay *splay_next(Splay *node)
+{
+ return node->flink;
+}
+
+Splay *splay_prev(Splay *node)
+{
+ return node->blink;
+}
+
+Splay *splay_nil(Splay *tree)
+{
+ return tree;
+}
+
+void free_splay(Splay *tree)
+{
+ Splay *ptr;
+
+ while (1) {
+ ptr = splay_first(tree);
+ if (!ptr->is_sentinel) {
+ splay_delete_node(ptr);
+ } else {
+ free(ptr);
+ return;
+ }
+ }
+}
+
+ Splay *splay_find_nearest_ptr(Splay *tree, unsigned long key, int *cmpval)
+{
+ Splay *s, *last;
+ int cmp;
+
+ last = tree;
+ s = splay_root(tree);
+ cmp = 1;
+
+ while(s != NULL) {
+ last = s;
+ if (key == s->key) {
+ *cmpval = 0;
+ return s;
+ } else if (key < (s->key)) {
+ s = s->left;
+ cmp = -1;
+ } else {
+ if (key < (s->val + s->key)) {
+ *cmpval = 0;
+ return s;
+ }
+ s = s->right;
+ cmp = 1;
+ }
+ }
+
+ *cmpval = cmp;
+ return last;
+}
+
+
+Splay *splay_find_ptr(Splay *tree, unsigned long key)
+{
+ int cmpval;
+ Splay *s;
+
+ s = splay_find_nearest_ptr(tree, key, &cmpval);
+ splay(s);
+ if (cmpval == 0) return s; else return NULL;
+}
+
+
+Splay *splay_insert(Splay *tree, Jval key, Jval val, Splay *parent, int cmpval)
+{
+ Splay *s;
+
+ s = (Splay *) malloc(sizeof(struct splay));
+ s->is_sentinel = 0;
+ s->parent = parent;
+ s->left = NULL;
+ s->right = NULL;
+ s->key = key;
+ s->val = val;
+
+ /* Set the parent's correct child pointer. The only
+ subtle case here is when the key is already in
+ the tree -- then we need to find a leaf node
+ to use as a parent */
+
+ /* When we're done here, parent should point to the
+ new node's successor in the linked list */
+
+ if (parent->is_sentinel) {
+ parent->parent = s;
+ } else {
+ if (cmpval == 0) { /* If the key is already in the
+ tree, try to insert a new one as the
+ node's right child. If the node already
+ has a right child, then try to insert the
+ new one as a left child. If there is already
+ a left child, then go to parent-flink and
+ insert the node as its left child. */
+ if (parent->right == NULL) {
+ cmpval = 1;
+ } else if (parent->left == NULL) {
+ cmpval = -1;
+ } else {
+ parent = parent->flink;
+ s->parent = parent;
+ cmpval = -1;
+ }
+ }
+ if (cmpval > 0) { /* Insert as right child */
+ if (parent->right != NULL) {
+ fprintf(stderr, "splay_insert error: parent->right != NULL");
+ exit(1);
+ }
+ parent->right = s;
+ parent = parent->flink;
+ } else {
+ if (parent->left != NULL) {
+ fprintf(stderr, "splay_insert error: parent->left != NULL");
+ exit(1);
+ }
+ parent->left = s;
+ }
+ }
+
+ s->flink = parent;
+ s->blink = parent->blink;
+ s->flink->blink = s;
+ s->blink->flink = s;
+ splay(s);
+ return s;
+}
+
+Splay *splay_insert_ptr(Splay *tree, unsigned long key, Jval val)
+{
+ Splay *parent, *s;
+ int cmpval;
+
+ parent = splay_find_nearest_ptr(tree, key, &cmpval);
+ return splay_insert(tree, key, val, parent, cmpval);
+}
+
+extern void splay_delete_node(Splay *node)
+{
+ Splay *left, *right, *tree, *newroot;
+
+ splay(node);
+
+ tree = node->parent;
+
+ left = node->left;
+ right = node->right;
+ newroot = node->flink;
+
+ node->flink->blink = node->blink;
+ node->blink->flink = node->flink;
+
+ free(node);
+
+ if (right == NULL && left == NULL) {
+ tree->parent = NULL;
+ } else if (right == NULL) {
+ tree->parent = left;
+ left->parent = tree;
+ } else if (left == NULL) {
+ tree->parent = right;
+ right->parent = tree;
+ } else {
+ tree->parent = right;
+ right->parent = tree;
+ splay(newroot);
+ newroot->left = left;
+ left->parent = newroot;
+ }
+}
+ Splay *finish_gte(int cmpval, Splay *s, int *found)
+{
+
+ if (cmpval == 0) {
+ *found = 1;
+ return s;
+ } else if (cmpval < 0) {
+ *found = 0;
+ return s;
+ } else {
+ *found = 1;
+ return s->flink;
+ }
+}
+/*
+Splay *splay_find_gte_str(Splay *tree, char *key, int *found)
+{
+ int cmpval;
+ Splay *s;
+
+ s = splay_find_nearest_str(tree, key, &cmpval);
+ return finish_gte(cmpval, s, found);
+}
+*/
+
+Splay *splay_find_gte_ptr(Splay *tree, unsigned long key, int *found)
+{
+ int cmpval;
+ Splay *s;
+
+ s = splay_find_nearest_ptr(tree, key, &cmpval);
+ return finish_gte(cmpval, s, found);
+}
+
+
diff --git a/safecode/runtime/BoundsCheckAllocator/splay.h b/safecode/runtime/BoundsCheckAllocator/splay.h
new file mode 100755
index 0000000..c31e19d
--- /dev/null
+++ b/safecode/runtime/BoundsCheckAllocator/splay.h
@@ -0,0 +1,48 @@
+// Note: This file is obtained from
+// http://www.cs.utk.edu/~cs140/spring-2005/notes/Splay/
+// FIXME: This may not be the most efficient version of splay implementation
+// This may be updated with a different splay implementation in near future
+#ifndef _SPLAY_
+#define SPLAY
+
+typedef unsigned long Jval ;
+
+/* Node identities */
+
+#define SPLAY_SENTINEL 0
+#define SPLAY_OTHER 1
+
+typedef struct splay {
+ Jval key;
+ Jval val;
+ int is_sentinel;
+ struct splay *left;
+ struct splay *right;
+ struct splay *flink;
+ struct splay *blink;
+ struct splay *parent;
+} Splay;
+
+extern "C" {
+ Splay *new_splay();
+ void free_splay(Splay *);
+ Splay *splay_insert_ptr(Splay *tree, unsigned long key, Jval val);
+ Splay *splay_find_ptr(Splay *tree, unsigned long key);
+ Splay *splay_find_gte_ptr(Splay *tree, unsigned long key, int *found);
+
+ Splay *splay_root(Splay *tree);
+ Splay *splay_first(Splay *tree);
+ Splay *splay_last(Splay *tree);
+ Splay *splay_next(Splay *node);
+ Splay *splay_prev(Splay *node);
+ Splay *splay_nil(Splay *tree);
+
+ void splay_delete_node(Splay *node);
+}
+
+#define splay_traverse(ptr, list) \
+ for (ptr = splay_first(list); ptr != splay_nil(list); ptr = splay_next(ptr))
+#define splay_rtraverse(ptr, list) \
+ for (ptr = splay_last(list); ptr != splay_nil(list); ptr = splay_prev(ptr))
+
+#endif
diff --git a/safecode/runtime/KernelSafePoolAllocator/Makefile b/safecode/runtime/KernelSafePoolAllocator/Makefile
new file mode 100755
index 0000000..8d133c3
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/Makefile
@@ -0,0 +1,8 @@
+LEVEL = ../..
+BYTECODE_LIBRARY=1
+LIBRARYNAME=poolalloc_kernel_safe_rt
+
+include $(LEVEL)/Makefile.common
+
+# Always build optimized and debug versions
+all:: $(LIBNAME_OBJO) $(LIBNAME_OBJG)
diff --git a/safecode/runtime/KernelSafePoolAllocator/PageManager.cpp b/safecode/runtime/KernelSafePoolAllocator/PageManager.cpp
new file mode 100755
index 0000000..32e5643
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/PageManager.cpp
@@ -0,0 +1,134 @@
+//===- PageManager.cpp - Implementation of the page allocator -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PageManager.h interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PageManager.h"
+#ifndef _POSIX_MAPPED_FILES
+#define _POSIX_MAPPED_FILES
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include "poolalloc/Support/MallocAllocator.h"
+#include "poolalloc/MMAPSupport.h"
+#include <iostream>
+#include <vector>
+#include <cassert>
+// Define this if we want to use memalign instead of mmap to get pages.
+// Empirically, this slows down the pool allocator a LOT.
+#define DEBUG(x)
+#define USE_MEMALIGN 0
+extern "C" {
+unsigned PageSize = 0;
+}
+FILE *fd1;
+void InitializePageManager() {
+ if (!PageSize) {
+ // fd1 = fopen("/tmp/ftpdlog", "a");
+ // sleep(10);
+ PageSize = sysconf(_SC_PAGESIZE) ;
+ }
+}
+
+#if !USE_MEMALIGN
+static void *GetPages(unsigned NumPages) {
+#if defined(i386) || defined(__i386__) || defined(__x86__)
+ /* Linux and *BSD tend to have these flags named differently. */
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+# define MAP_ANONYMOUS MAP_ANON
+#endif /* defined(MAP_ANON) && !defined(MAP_ANONYMOUS) */
+#elif defined(sparc) || defined(__sparc__) || defined(__sparcv9)
+ /* nothing */
+#else
+ std::cerr << "This architecture is not supported by the pool allocator!\n";
+ abort();
+#endif
+
+#if defined(__linux__)
+#define fd 0
+#else
+#define fd -1
+#endif
+ void *Addr;
+ //MMAP DOESNOT WORK !!!!!!!!
+ // Addr = mmap(0, NumPages*PageSize, PROT_READ|PROT_WRITE,
+ // MAP_SHARED|MAP_ANONYMOUS, fdq, 0);
+ // void *pa = malloc(NumPages * PageSize);
+ // assert(Addr != MAP_FAILED && "MMAP FAILED!");
+ if (posix_memalign(&Addr, PageSize, NumPages*PageSize) != 0){
+ assert(1 && "memalign failed \n");
+ }
+ DEBUG(printf("memalign returns %x for %d\n", Addr, NumPages);)
+ // fprintf(fd1, "memory usage statistic :%d %d\n", getpid(), poolmemusage);
+ // fflush(fd1);
+ return Addr;
+}
+#endif
+
+// Explicitly use the malloc allocator here, to avoid depending on the C++
+// runtime library.
+typedef std::vector<void*, llvm::MallocAllocator<void*> > FreePagesListType;
+
+static FreePagesListType &getFreePageList() {
+ static FreePagesListType *FreePages = 0;
+
+ if (!FreePages) {
+ // Avoid using operator new!
+ FreePages = (FreePagesListType*)malloc(sizeof(FreePagesListType));
+ // Use placement new now.
+ // new (FreePages) std::vector<void*, llvm::MallocAllocator<void*> >();
+ }
+ return *FreePages;
+}
+
+/// AllocatePage - This function returns a chunk of memory with size and
+/// alignment specified by PageSize.
+void *AllocatePage() {
+ // return GetPages(1);
+ FreePagesListType &FPL = getFreePageList();
+
+ if (!FPL.empty()) {
+ void *Result = FPL.back();
+ FPL.pop_back();
+ return Result;
+ }
+
+ // Allocate several pages, and put the extras on the freelist...
+ unsigned NumToAllocate = 1;
+ char *Ptr = (char*)GetPages(NumToAllocate);
+ /*
+ for (unsigned i = 1; i != NumToAllocate; ++i)
+ FPL.push_back(Ptr+i*PageSize);
+ */
+ return Ptr;
+}
+
+void *AllocateNPages(unsigned Num) {
+ if (Num <= 1) return AllocatePage();
+ return GetPages(Num);
+}
+
+/// FreePage - This function returns the specified page to the pagemanager for
+/// future allocation.
+#define THRESHOLD 5
+void FreePage(void *Page) {
+ FreePagesListType &FPL = getFreePageList();
+ FPL.push_back(Page);
+ //munmap(Page, 1);
+ /*
+ if (FPL.size() > THRESHOLD) {
+ // printf( "pool allocator : reached a threshold \n");
+ // exit(-1);
+ munmap(Page, PageSize);
+ poolmemusage -= PageSize;
+ }
+ */
+}
diff --git a/safecode/runtime/KernelSafePoolAllocator/PageManager.h b/safecode/runtime/KernelSafePoolAllocator/PageManager.h
new file mode 100755
index 0000000..ec57652
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/PageManager.h
@@ -0,0 +1,40 @@
+//===- PageManager.h - Allocates memory on page boundaries ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface used by the pool allocator to allocate memory
+// on large alignment boundaries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PAGEMANAGER_H
+#define PAGEMANAGER_H
+
+/// InitializePageManager - This function must be called before any other page
+/// manager accesses are performed. It may be called multiple times.
+///
+void InitializePageManager();
+
+/// PageSize - Contains the size of the unit of memory allocated by
+/// AllocatePage. This is a value that is typically several kilobytes in size,
+/// and is guaranteed to be a power of two.
+///
+extern unsigned PageSize;
+
+/// AllocatePage - This function returns a chunk of memory with size and
+/// alignment specified by getPageSize().
+void *AllocatePage();
+
+/// AllocateNPages -
+void *AllocateNPages(unsigned Num);
+
+/// FreePage - This function returns the specified page to the pagemanager for
+/// future allocation.
+void FreePage(void *Page);
+
+#endif
diff --git a/safecode/runtime/KernelSafePoolAllocator/PoolAllocator.h b/safecode/runtime/KernelSafePoolAllocator/PoolAllocator.h
new file mode 100755
index 0000000..c19bd14
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/PoolAllocator.h
@@ -0,0 +1,77 @@
+//===- PoolAllocator.h - Pool allocator runtime interface file --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface which is implemented by the LLVM pool
+// allocator runtime library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POOLALLOCATOR_RUNTIME_H
+#define POOLALLOCATOR_RUNTIME_H
+
+#include "llvm/ADT/hash_set"
+#include "PoolCheck.h"
+#include "splay.h"
+
+#define AddrArrSize 2
+#define POOLCHECK(x) x
+
+typedef struct PoolTy {
+ // Ptr1, Ptr2 - Implementation specified data pointers.
+ void *Ptr1, *Ptr2;
+
+ // NodeSize - Keep track of the object size tracked by this pool
+ unsigned short NodeSize;
+
+ // FreeablePool - Set to false if the memory from this pool cannot be freed
+ // before destroy.
+ //
+ // unsigned short FreeablePool;
+
+ // Use the hash_set only if the number of Slabs exceeds AddrArrSize
+ hash_set<void*> *Slabs;
+
+ // The array containing the initial address of slabs (as long as there are
+ // fewer than a certain number of them)
+ unsigned SlabAddressArray[AddrArrSize];
+
+ // The number of slabs allocated. Large arrays are not counted
+ unsigned NumSlabs;
+
+ // Large arrays. In SAFECode, these are currently not freed or reused.
+ // A better implementation could split them up into single slabs for reuse,
+ // upon being freed.
+ void *LargeArrays;
+
+ void *prevPage[4];
+ unsigned short lastUsed;
+
+ POOLCHECK(Splay *splay;)
+ POOLCHECK(PoolCheckSlab *PCS;)
+
+} PoolTy;
+
+
+
+extern "C" {
+ void poolinit(PoolTy *Pool, unsigned NodeSize);
+ void poolmakeunfreeable(PoolTy *Pool);
+ void pooldestroy(PoolTy *Pool);
+ void *poolalloc(PoolTy *Pool, unsigned NumBytes);
+ void poolfree(PoolTy *Pool, void *Node);
+
+ void *poolrealloc(PoolTy *Pool, void *Node, unsigned NumBytes);
+ void *poolallocatorcheck(PoolTy *Pool, void *Node);
+
+
+ //Extra functions for poolcheck
+ void poolregister(PoolTy *Pool, void *allocadptr, unsigned NumBytes);
+}
+
+#endif
diff --git a/safecode/runtime/KernelSafePoolAllocator/PoolAllocatorBitMask.cpp b/safecode/runtime/KernelSafePoolAllocator/PoolAllocatorBitMask.cpp
new file mode 100755
index 0000000..82f354f
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/PoolAllocatorBitMask.cpp
@@ -0,0 +1,1170 @@
+//===- PoolAllocatorBitMask.cpp - Implementation of poolallocator runtime -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is one possible implementation of the LLVM pool allocator runtime
+// library.
+//
+// This uses the 'Ptr1' field to maintain a linked list of slabs that are either
+// empty or are partially allocated from. The 'Ptr2' field of the PoolTy is
+// used to track a linked list of slabs which are full, ie, all elements have
+// been allocated from them.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PoolAllocator.h"
+#include "PoolCheck.h"
+#include "PageManager.h"
+#include <cassert>
+#include <cstdlib>
+#include <cstdio>
+#include <unistd.h>
+#define DEBUG(x)
+#define POOLCHECK(x) x
+//===----------------------------------------------------------------------===//
+//
+// PoolSlab implementation
+//
+//===----------------------------------------------------------------------===//
+unsigned ArrayBoundsCheck = 1;
+
+// PoolSlab Structure - Hold multiple objects of the current node type.
+// Invariants: FirstUnused <= UsedEnd
+//
+struct PoolSlab {
+ PoolSlab **PrevPtr, *Next;
+ bool isSingleArray; // If this slab is used for exactly one array
+ PoolSlab * OrigSlab;
+private:
+ // FirstUnused - First empty node in slab
+ unsigned short FirstUnused;
+
+ // UsedBegin - The first node in the slab that is used.
+ unsigned short UsedBegin;
+
+ // UsedEnd - 1 past the last allocated node in slab. 0 if slab is empty
+ unsigned short UsedEnd;
+
+ // NumNodesInSlab - This contains the number of nodes in this slab, which
+ // effects the size of the NodeFlags vector, and indicates the number of nodes
+ // which are in the slab.
+ unsigned int NumNodesInSlab;
+ // NodeFlagsVector - This array contains two bits for each node in this pool
+ // slab. The first (low address) bit indicates whether this node has been
+ // allocated, and the second (next higher) bit indicates whether this is the
+ // start of an allocation.
+ //
+ // This is a variable sized array, which has 2*NumNodesInSlab bits (rounded up
+ // to 4 bytes).
+ unsigned NodeFlagsVector1;
+ bool isNodeAllocated(unsigned NodeNum) {
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ return NodeFlagsVector[NodeNum/16] & (1 << (NodeNum & 15));
+ }
+
+ void markNodeAllocated(unsigned NodeNum) {
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ NodeFlagsVector[NodeNum/16] |= 1 << (NodeNum & 15);
+ }
+
+ void markNodeFree(unsigned NodeNum) {
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ NodeFlagsVector[NodeNum/16] &= ~(1 << (NodeNum & 15));
+ }
+
+ void setStartBit(unsigned NodeNum) {
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ NodeFlagsVector[NodeNum/16] |= 1 << ((NodeNum & 15)+16);
+ }
+
+ bool isStartOfAllocation(unsigned NodeNum) {
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ return NodeFlagsVector[NodeNum/16] & (1 << ((NodeNum & 15)+16));
+ }
+
+ void clearStartBit(unsigned NodeNum) {
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ NodeFlagsVector[NodeNum/16] &= ~(1 << ((NodeNum & 15)+16));
+ }
+
+public:
+ // create - Create a new (empty) slab and add it to the end of the Pools list.
+ static PoolSlab *create(PoolTy *Pool);
+
+ // createSingleArray - Create a slab for a large singlearray with NumNodes
+ // entries in it, returning the pointer into the pool directly.
+ static void *createSingleArray(PoolTy *Pool, unsigned NumNodes);
+
+ // getSlabSize - Return the number of nodes that each slab should contain.
+ static unsigned getSlabSize(PoolTy *Pool) {
+ // We need space for the header...
+ unsigned NumNodes = PageSize-sizeof(PoolSlab);
+
+ // We need space for the NodeFlags...
+ unsigned NodeFlagsBytes = NumNodes/Pool->NodeSize * 2 / 8;
+ NumNodes -= (NodeFlagsBytes+3) & ~3; // Round up to int boundaries.
+
+ // Divide the remainder among the nodes!
+ return NumNodes / Pool->NodeSize;
+ }
+
+ void initialize(unsigned NodesPerSlab) ;
+
+ unsigned int GetNumNodesInSlab() {
+ return NumNodesInSlab;
+ }
+
+ void addToList(PoolSlab **PrevPtrPtr) {
+ PoolSlab *InsertBefore = *PrevPtrPtr;
+ *PrevPtrPtr = this;
+ PrevPtr = PrevPtrPtr;
+ Next = InsertBefore;
+ if (InsertBefore) InsertBefore->PrevPtr = &Next;
+ }
+
+ void unlinkFromList() {
+ *PrevPtr = Next;
+ if (Next) Next->PrevPtr = PrevPtr;
+ }
+
+ unsigned getSlabSize() const {
+ return NumNodesInSlab;
+ }
+
+ // destroy - Release the memory for the current object.
+ void destroy();
+
+
+ // Unmap - Release the memory for the current object.
+ void mprotect();
+
+ // isEmpty - This is a quick check to see if this slab is completely empty or
+ // not.
+ bool isEmpty() const { return UsedEnd == 0; }
+
+ // isFull - This is a quick check to see if the slab is completely allocated.
+ //
+ bool isFull() const { return isSingleArray || FirstUnused == getSlabSize(); }
+
+ // allocateSingle - Allocate a single element from this pool, returning -1 if
+ // there is no space.
+ int allocateSingle();
+
+ // allocateMultiple - Allocate multiple contiguous elements from this pool,
+ // returning -1 if there is no space.
+ int allocateMultiple(unsigned Num);
+
+ // getElementAddress - Return the address of the specified element.
+ void *getElementAddress(unsigned ElementNum, unsigned ElementSize) {
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ char *Data = (char*)&NodeFlagsVector[((unsigned)NumNodesInSlab+15)/16];
+ return &Data[ElementNum*ElementSize];
+ }
+ const void *getElementAddress(unsigned ElementNum, unsigned ElementSize)const{
+ const unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ const char *Data =
+ (const char *)&NodeFlagsVector[(unsigned)(NumNodesInSlab+15)/16];
+ return &Data[ElementNum*ElementSize];
+ }
+
+ // containsElement - Return the element number of the specified address in
+ // this slab. If the address is not in slab, return -1.
+ int containsElement(void *Ptr, unsigned ElementSize) const;
+
+ // freeElement - Free the single node, small array, or entire array indicated.
+ void freeElement(unsigned short ElementIdx);
+
+ // lastNodeAllocated - Return one past the last node in the pool which is
+ // before ScanIdx, that is allocated. If there are no allocated nodes in this
+ // slab before ScanIdx, return 0.
+ unsigned lastNodeAllocated(unsigned ScanIdx);
+};
+
+// create - Create a new (empty) slab and add it to the end of the Pools list.
+PoolSlab *PoolSlab::create(PoolTy *Pool) {
+ unsigned NodesPerSlab = getSlabSize(Pool);
+
+ unsigned Size = sizeof(PoolSlab) + 4*((NodesPerSlab+15)/16) +
+ Pool->NodeSize*getSlabSize(Pool);
+ assert(Size <= PageSize && "Trying to allocate a slab larger than a page!");
+ PoolSlab *PS = (PoolSlab*)AllocatePage();
+
+ PS->NumNodesInSlab = NodesPerSlab;
+ PS->OrigSlab = PS;
+ PS->isSingleArray = 0; // Not a single array!
+ PS->FirstUnused = 0; // Nothing allocated.
+ PS->UsedBegin = 0; // Nothing allocated.
+ PS->UsedEnd = 0; // Nothing allocated.
+
+ // Add the slab to the list...
+ PS->addToList((PoolSlab**)&Pool->Ptr1);
+ // printf(" creating a slab %x\n", PS);
+ return PS;
+}
+
+void *PoolSlab::createSingleArray(PoolTy *Pool, unsigned NumNodes) {
+ // FIXME: This wastes memory by allocating space for the NodeFlagsVector
+ unsigned NodesPerSlab = getSlabSize(Pool);
+ assert(NumNodes > NodesPerSlab && "No need to create a single array!");
+
+ unsigned NumPages = (NumNodes+NodesPerSlab-1)/NodesPerSlab;
+ PoolSlab *PS = (PoolSlab*)AllocateNPages(NumPages);
+
+ assert(PS && "poolalloc: Could not allocate memory!");
+
+ if (Pool->NumSlabs > AddrArrSize)
+ Pool->Slabs->insert((void*)PS);
+ else if (Pool->NumSlabs == AddrArrSize) {
+ // Create the hash_set
+ Pool->Slabs = new hash_set<void *>;
+ Pool->Slabs->insert((void *)PS);
+ for (unsigned i = 0; i < AddrArrSize; ++i)
+ Pool->Slabs->insert((void *) Pool->SlabAddressArray[i]);
+ } else {
+ // Insert it in the array
+ Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) PS;
+ }
+ Pool->NumSlabs++;
+
+ PS->addToList((PoolSlab**)&Pool->LargeArrays);
+
+ PS->isSingleArray = 1;
+ PS->OrigSlab = PS;
+ PS->NumNodesInSlab = NumPages * PageSize;
+ *(unsigned*)&PS->FirstUnused = NumPages;
+ return PS->getElementAddress(0, 0);
+}
+void MprotectPage(void *pa, unsigned numPages);
+
+void PoolSlab::mprotect() {
+ if (isSingleArray) {
+ unsigned NumPages = *(unsigned*)&FirstUnused;
+ MprotectPage((char*)this, NumPages);
+ }
+ else
+ MprotectPage(this, 1);
+}
+
+void PoolSlab::destroy() {
+ if (isSingleArray)
+ for (unsigned NumPages = *(unsigned*)&FirstUnused; NumPages != 1;--NumPages)
+ FreePage((char*)this + (NumPages-1)*PageSize);
+
+ FreePage(this);
+}
+
+// allocateSingle - Allocate a single element from this pool, returning -1 if
+// there is no space.
+int PoolSlab::allocateSingle() {
+ // If the slab is a single array, go on to the next slab. Don't allocate
+ // single nodes in a SingleArray slab.
+ if (isSingleArray) return -1;
+
+ unsigned SlabSize = PoolSlab::getSlabSize();
+
+ // Check to see if there are empty entries at the end of the slab...
+ if (UsedEnd < SlabSize) {
+ // Mark the returned entry used
+ unsigned short UE = UsedEnd;
+ markNodeAllocated(UE);
+ setStartBit(UE);
+
+ // If we are allocating out the first unused field, bump its index also
+ if (FirstUnused == UE)
+ FirstUnused++;
+
+ // Return the entry, increment UsedEnd field.
+ return UsedEnd++;
+ }
+
+ // If not, check to see if this node has a declared "FirstUnused" value that
+ // is less than the number of nodes allocated...
+ //
+ if (FirstUnused < SlabSize) {
+ // Successfully allocate out the first unused node
+ unsigned Idx = FirstUnused;
+ markNodeAllocated(Idx);
+ setStartBit(Idx);
+
+ // Increment FirstUnused to point to the new first unused value...
+ // FIXME: this should be optimized
+ unsigned short FU = FirstUnused;
+ do {
+ ++FU;
+ } while (FU != SlabSize && isNodeAllocated(FU));
+ FirstUnused = FU;
+
+ return Idx;
+ }
+
+ return -1;
+}
+
+// allocateMultiple - Allocate multiple contiguous elements from this pool,
+// returning -1 if there is no space.
+int PoolSlab::allocateMultiple(unsigned Size) {
+ // Do not allocate small arrays in SingleArray slabs
+ if (isSingleArray) return -1;
+
+ // For small array allocation, check to see if there are empty entries at the
+ // end of the slab...
+ if (UsedEnd+Size <= getSlabSize()) {
+ // Mark the returned entry used and set the start bit
+ unsigned UE = UsedEnd;
+ setStartBit(UE);
+ for (unsigned i = UE; i != UE+Size; ++i)
+ markNodeAllocated(i);
+
+ // If we are allocating out the first unused field, bump its index also
+ if (FirstUnused == UE)
+ FirstUnused += Size;
+
+ // Increment UsedEnd
+ UsedEnd += Size;
+
+ // Return the entry
+ return UE;
+ }
+
+ // If not, check to see if this node has a declared "FirstUnused" value
+ // starting which Size nodes can be allocated
+ //
+ unsigned Idx = FirstUnused;
+ while (Idx+Size <= getSlabSize()) {
+ assert(!isNodeAllocated(Idx) && "FirstUsed is not accurate!");
+
+ // Check if there is a continuous array of Size nodes starting FirstUnused
+ unsigned LastUnused = Idx+1;
+ for (; LastUnused != Idx+Size && !isNodeAllocated(LastUnused); ++LastUnused)
+ /*empty*/;
+
+ // If we found an unused section of this pool which is large enough, USE IT!
+ if (LastUnused == Idx+Size) {
+ setStartBit(Idx);
+ // FIXME: this loop can be made more efficient!
+ for (unsigned i = Idx; i != Idx + Size; ++i)
+ markNodeAllocated(i);
+
+ // This should not be allocating on the end of the pool, so we don't need
+ // to bump the UsedEnd pointer.
+ assert(Idx != UsedEnd && "Shouldn't allocate at end of pool!");
+
+ // If we are allocating out the first unused field, bump its index also.
+ if (Idx == FirstUnused)
+ FirstUnused += Size;
+
+ // Return the entry
+ return Idx;
+ }
+
+ // Otherwise, try later in the pool. Find the next unused entry.
+ Idx = LastUnused;
+ while (Idx+Size <= getSlabSize() && isNodeAllocated(Idx))
+ ++Idx;
+ }
+
+ return -1;
+}
+
+
+// containsElement - Return the element number of the specified address in
+// this slab. If the address is not in slab, return -1.
+int PoolSlab::containsElement(void *Ptr, unsigned ElementSize) const {
+ const void *FirstElement = getElementAddress(0, 0);
+ if (FirstElement <= Ptr) {
+ unsigned Delta = (char*)Ptr-(char*)FirstElement;
+ if (isSingleArray)
+ if (Delta < NumNodesInSlab) return Delta/ElementSize;
+ unsigned Index = Delta/ElementSize;
+ if (Index < getSlabSize()) {
+ if (Delta % ElementSize != 0) {
+ printf("Freeing pointer into the middle of an element!");
+ abort();
+ }
+
+ return Index;
+ }
+ }
+ return -1;
+}
+
+void PoolSlab::initialize(unsigned NodesPerSlab) {
+
+ NumNodesInSlab = NodesPerSlab;
+ isSingleArray = 0; // Not a single array!
+ FirstUnused = 0; // Nothing allocated.
+ UsedBegin = 0; // Nothing allocated.
+ UsedEnd = 0; // Nothing allocated.
+
+ // Add the slab to the list...
+}
+// freeElement - Free the single node, small array, or entire array indicated.
+void PoolSlab::freeElement(unsigned short ElementIdx) {
+ if (!isNodeAllocated(ElementIdx)) return;
+ // assert(isNodeAllocated(ElementIdx) &&
+ // "poolfree: Attempt to free node that is already freed\n");
+ // assert(!isSingleArray && "Cannot free an element from a single array!");
+
+ // Mark this element as being free!
+ markNodeFree(ElementIdx);
+
+ // If this slab is not a SingleArray
+ assert(isStartOfAllocation(ElementIdx) &&
+ "poolfree: Attempt to free middle of allocated array\n");
+
+ // Free the first cell
+ clearStartBit(ElementIdx);
+ markNodeFree(ElementIdx);
+
+ // Free all nodes if this was a small array allocation.
+ unsigned short ElementEndIdx = ElementIdx + 1;
+
+ // FIXME: This should use manual strength reduction to produce decent code.
+ unsigned short UE = UsedEnd;
+ while (ElementEndIdx != UE &&
+ !isStartOfAllocation(ElementEndIdx) &&
+ isNodeAllocated(ElementEndIdx)) {
+ markNodeFree(ElementEndIdx);
+ ++ElementEndIdx;
+ }
+
+ // Update the first free field if this node is below the free node line
+ if (ElementIdx < FirstUnused) FirstUnused = ElementIdx;
+
+ // Update the first used field if this node was the first used.
+ if (ElementIdx == UsedBegin) UsedBegin = ElementEndIdx;
+
+ // If we are freeing the last element in a slab, shrink the UsedEnd marker
+ // down to the last used node.
+ if (ElementEndIdx == UE) {
+#if 0
+ printf("FU: %d, UB: %d, UE: %d FREED: [%d-%d)",
+ FirstUnused, UsedBegin, UsedEnd, ElementIdx, ElementEndIdx);
+#endif
+
+ // If the user is freeing the slab entirely in-order, it's quite possible
+ // that all nodes are free in the slab. If this is the case, simply reset
+ // our pointers.
+ if (UsedBegin == UE) {
+ //printf(": SLAB EMPTY\n");
+ FirstUnused = 0;
+ UsedBegin = 0;
+ UsedEnd = 0;
+ } else if (FirstUnused == ElementIdx) {
+ // Freed the last node(s) in this slab.
+ FirstUnused = ElementIdx;
+ UsedEnd = ElementIdx;
+ } else {
+ UsedEnd = lastNodeAllocated(ElementIdx);
+ assert(FirstUnused <= UsedEnd+1 &&
+ "FirstUnused field was out of date!");
+ }
+ }
+}
+
+unsigned PoolSlab::lastNodeAllocated(unsigned ScanIdx) {
+ // Check the last few nodes in the current word of flags...
+ unsigned CurWord = ScanIdx/16;
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ unsigned short Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+ if (Flags) {
+ // Mask off nodes above this one
+ Flags &= (1 << ((ScanIdx & 15)+1))-1;
+ if (Flags) {
+ // If there is still something in the flags vector, then there is a node
+ // allocated in this part. The goto is a hack to get the uncommonly
+ // executed code away from the common code path.
+ //printf("A: ");
+ goto ContainsAllocatedNode;
+ }
+ }
+
+ // Ok, the top word doesn't contain anything, scan the whole flag words now.
+ --CurWord;
+ while (CurWord != ~0U) {
+ unsigned * NodeFlagsVector = &NodeFlagsVector1;
+ Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+ if (Flags) {
+ // There must be a node allocated in this word!
+ //printf("B: ");
+ goto ContainsAllocatedNode;
+ }
+ CurWord--;
+ }
+ return 0;
+
+ContainsAllocatedNode:
+ // Figure out exactly which node is allocated in this word now. The node
+ // allocated is the one with the highest bit set in 'Flags'.
+ //
+ // This should use __builtin_clz to get the value, but this builtin is only
+ // available with GCC 3.4 and above. :(
+ assert(Flags && "Should have allocated node!");
+
+ unsigned short MSB;
+#if GCC3_4_EVENTUALLY
+ MSB = 16 - ::__builtin_clz(Flags);
+#else
+ for (MSB = 15; (Flags & (1U << MSB)) == 0; --MSB)
+ /*empty*/;
+#endif
+
+ assert((1U << MSB) & Flags); // The bit should be set
+ assert((~(1U << MSB) & Flags) < Flags);// Removing it should make flag smaller
+ ScanIdx = CurWord*16 + MSB;
+ assert(isNodeAllocated(ScanIdx));
+ return ScanIdx;
+}
+
+
+//===----------------------------------------------------------------------===//
+//
+// Pool allocator library implementation
+//
+//===----------------------------------------------------------------------===//
+
+// poolinit - Initialize a pool descriptor to empty
+//
+void poolinit(PoolTy *Pool, unsigned NodeSize) {
+ assert(Pool && "Null pool pointer passed into poolinit!\n");
+ DEBUG(printf("pool init %x, %d\n", Pool, NodeSize);)
+
+ // Ensure the page manager is initialized
+ InitializePageManager();
+
+ // We must alway return unique pointers, even if they asked for 0 bytes
+ Pool->NodeSize = NodeSize ? NodeSize : 1;
+ Pool->Ptr1 = Pool->Ptr2 = 0;
+ Pool->LargeArrays = 0;
+ // For SAFECode, we set FreeablePool to 0 always
+ // Pool->FreeablePool = 0;
+ Pool->lastUsed = 0;
+ Pool->prevPage[0] = 0;
+ Pool->prevPage[1] = 0;
+ // Initialize the SlabAddressArray to zero
+ for (int i = 0; i < AddrArrSize; ++i) {
+ Pool->SlabAddressArray[i] = 0;
+ }
+
+ Pool->NumSlabs = 0;
+ POOLCHECK(poolcheckinit(Pool, NodeSize);)
+ POOLCHECK(Pool->splay = new_splay();)
+ POOLCHECK(Pool->PCS = 0;)
+ /// Pool->Slabs = new hash_set<void*>;
+ // Call hash_set constructor explicitly
+ // void *SlabPtr = &Pool->Slabs;
+ // new (SlabPtr) hash_set<void*>;
+}
+
+void poolmakeunfreeable(PoolTy *Pool) {
+ assert(Pool && "Null pool pointer passed in to poolmakeunfreeable!\n");
+ // Pool->FreeablePool = 0;
+}
+
+// pooldestroy - Release all memory allocated for a pool
+//
+void pooldestroy(PoolTy *Pool) {
+ DEBUG(printf("pooldestroying %x\n", Pool);)
+ assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+ if (Pool->NumSlabs > AddrArrSize) {
+ Pool->Slabs->clear();
+ delete Pool->Slabs;
+ }
+ POOLCHECK(free_splay(Pool->splay);)
+ // Free any partially allocated slabs
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+ while (PS) {
+ PoolSlab *Next = PS->Next;
+ PS->destroy();
+ PS = Next;
+ }
+
+ // Free the completely allocated slabs
+ PS = (PoolSlab*)Pool->Ptr2;
+ while (PS) {
+ PoolSlab *Next = PS->Next;
+ PS->destroy();
+ PS = Next;
+ }
+
+ // Free the large arrays
+ PS = (PoolSlab*)Pool->LargeArrays;
+ while (PS) {
+ PoolSlab *Next = PS->Next;
+ PS->destroy();
+ PS = Next;
+ }
+
+ POOLCHECK(poolcheckdestroy(Pool);)
+}
+
+
+// poolallocarray - a helper function used to implement poolalloc, when the
+// number of nodes to allocate is not 1.
+static void *poolallocarray(PoolTy* Pool, unsigned Size) {
+ assert(Pool && "Null pool pointer passed into poolallocarray!\n");
+ if (Size > PoolSlab::getSlabSize(Pool))
+ return PoolSlab::createSingleArray(Pool, Size);
+
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+
+ // Loop through all of the slabs looking for one with an opening
+ for (; PS; PS = PS->Next) {
+ int Element = PS->allocateMultiple(Size);
+ if (Element != -1) {
+ // We allocated an element. Check to see if this slab has been completely
+ // filled up. If so, move it to the Ptr2 list.
+ if (PS->isFull()) {
+ PS->unlinkFromList();
+ PS->addToList((PoolSlab**)&Pool->Ptr2);
+ }
+ return PS->getElementAddress(Element, Pool->NodeSize);
+ }
+ }
+
+ PoolSlab *New = PoolSlab::create(Pool);
+ POOLCHECK(poolcheckAddSlab(&Pool->PCS, New);)
+ if (Pool->NumSlabs > AddrArrSize) {
+ DEBUG(printf("new slab inserting %x \n", (void *)New);)
+ Pool->Slabs->insert((void *)New);
+ } else if (Pool->NumSlabs == AddrArrSize) {
+ // Create the hash_set
+ Pool->Slabs = new hash_set<void *>;
+ Pool->Slabs->insert((void *)New);
+ for (unsigned i = 0; i < AddrArrSize; ++i)
+ Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+ } else {
+ // Insert it in the array
+ Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) New;
+ }
+ Pool->NumSlabs++;
+
+ // return malloc(Size * Pool->NodeSize);
+ int Idx = New->allocateMultiple(Size);
+ assert(Idx == 0 && "New allocation didn't return zero'th node?");
+ return New->getElementAddress(0, 0);
+}
+
+void *poolalloc(PoolTy *Pool, unsigned NumBytes) {
+ // return malloc(Size * Pool->NodeSize);
+ void *retAddress = NULL;
+ if (!Pool) {
+ printf("Null pool pointer passed in to poolalloc!, FAILING\n");
+ exit(-1);
+ }
+ unsigned NodeSize = Pool->NodeSize;
+ unsigned NodesToAllocate1 = NumBytes / NodeSize;
+ if (NodesToAllocate1 == 0) {
+ // abort();
+ }
+ unsigned NodesToAllocate = (NumBytes+NodeSize-1)/NodeSize;
+ if (NodesToAllocate > 1) {
+ retAddress = poolallocarray(Pool, NodesToAllocate);
+ DEBUG(printf("poolalloc: Pool %x NodeSize %d retaddress %x numbytes %d\n",Pool, Pool->NodeSize, retAddress, NumBytes);)
+ POOLCHECK(poolcheckregister(Pool->splay, retAddress, NumBytes);)
+ return retAddress;
+ }
+
+ // Special case the most common situation, where a single node is being
+ // allocated.
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+
+ if (__builtin_expect(PS != 0, 1)) {
+ int Element = PS->allocateSingle();
+ if (__builtin_expect(Element != -1, 1)) {
+ // We allocated an element. Check to see if this slab has been
+ // completely filled up. If so, move it to the Ptr2 list.
+ if (__builtin_expect(PS->isFull(), false)) {
+ PS->unlinkFromList();
+ PS->addToList((PoolSlab**)&Pool->Ptr2);
+ }
+ retAddress = PS->getElementAddress(Element, NodeSize);
+ DEBUG(printf("poolalloc: Pool %x NodeSize %d retaddress %x numbytes %d\n",Pool, Pool->NodeSize, retAddress, NumBytes);)
+ POOLCHECK(poolcheckregister(Pool->splay, retAddress, NumBytes);)
+ return retAddress;
+ }
+
+ // Loop through all of the slabs looking for one with an opening
+ for (PS = PS->Next; PS; PS = PS->Next) {
+ int Element = PS->allocateSingle();
+ if (Element != -1) {
+ // We allocated an element. Check to see if this slab has been
+ // completely filled up. If so, move it to the Ptr2 list.
+ if (PS->isFull()) {
+ PS->unlinkFromList();
+ PS->addToList((PoolSlab**)&Pool->Ptr2);
+ }
+ retAddress = PS->getElementAddress(Element, NodeSize);
+ DEBUG(printf("poolalloc: Pool %x NodeSize %d retaddress %x numbytes %d\n",Pool, Pool->NodeSize, retAddress, NumBytes);)
+ POOLCHECK(poolcheckregister(Pool->splay, retAddress, NumBytes);)
+ return retAddress;
+ }
+ }
+ }
+
+ // Otherwise we must allocate a new slab and add it to the list
+ PoolSlab *New = PoolSlab::create(Pool);
+ POOLCHECK(poolcheckAddSlab(&Pool->PCS, New);)
+
+ if (Pool->NumSlabs > AddrArrSize)
+ Pool->Slabs->insert((void *)New);
+ else if (Pool->NumSlabs == AddrArrSize) {
+ // Create the hash_set
+ Pool->Slabs = new hash_set<void *>;
+ Pool->Slabs->insert((void *)New);
+ for (unsigned i = 0; i < AddrArrSize; ++i)
+ Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+ } else {
+ // Insert it in the array
+ Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) New;
+ }
+ Pool->NumSlabs++;
+
+ int Idx = New->allocateSingle();
+ assert(Idx == 0 && "New allocation didn't return zero'th node?");
+ retAddress = New->getElementAddress(0, 0);
+ DEBUG(printf("poolalloc: Pool %x NodeSize %d retaddress %x numbytes %d\n",Pool, Pool->NodeSize, retAddress, NumBytes);)
+ POOLCHECK(poolcheckregister(Pool->splay, retAddress, NumBytes);)
+ return retAddress;
+}
+
+/*
+// SearchForContainingSlab - This implementation uses the hash_set as well
+// as the array to search the list of allocated slabs for the node in question
+static PoolSlab *SearchForContainingSlab(PoolTy *Pool, void *Node,
+ unsigned &TheIndex) {
+ // printf("in pool check for pool %x, node %x\n",Pool,Node);
+ unsigned NodeSize = Pool->NodeSize;
+ void *PS;
+ if (!Pool) {
+ printf("Empty Pool in pool check FAILING \n");
+ exit(-1);
+ }
+ assert (Pool->AllocadPool <= 0 && "SearchForContainingSlab not to be called"
+ " for alloca'ed pools");
+
+ PS = (void*)((long)Node & ~(PageSize-1));
+ if (Pool->NumSlabs > AddrArrSize) {
+ hash_set<void*> &theSlabs = *Pool->Slabs;
+ if (theSlabs.find(PS) == theSlabs.end()) {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ unsigned Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PSlab = PSlab->Next;
+ }
+ if (Idx == -1) {
+ printf("poolcheck: node being checked not found in pool \n");
+ abort();
+ }
+ TheIndex = Idx;
+ return PSlab;
+ } else {
+ printf("poolcheck: node being checked not found in pool \n");
+ abort();
+ }
+ } else {
+ // Check that Node does not point to PoolSlab meta-data
+ if ((PoolSlab *)PS->getElementAddress(0,0) > (long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ abort();
+ }
+ TheIndex = PS->containsElement(Node, NodeSize);
+ return (PoolSlab *)PS;
+ }
+ } else {
+ bool found;
+ for (unsigned i = 0; i < AddrArrSize && !found; ++i) {
+ if (Pool->SlabAddressArray[i] == (unsigned) PS)
+ found = true;
+ }
+
+ if (found) {
+ // Check that Node does not point to PoolSlab meta-data
+ if ((PoolSlab *)PS->getElementAddress(0,0) > (long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ abort();
+ }
+ TheIndex = PS->containsElement(Node, NodeSize);
+ return (PoolSlab *)PS;
+ } else {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ unsigned Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PSlab = PSlab->Next;
+ }
+ if (Idx == -1) {
+ printf("poolcheck: node being checked not found in pool \n");
+ abort();
+ }
+ TheIndex = Idx;
+ return PSlab;
+ }
+ printf("poolcheck: node being checked not found in pool \n");
+ abort();
+ }
+ }
+}
+*/
+
+#if 0
+// SearchForContainingSlab - Do a brute force search through the list of
+// allocated slabs for the node in question.
+//
+static PoolSlab *SearchForContainingSlab(PoolTy *Pool, void *Node,
+ unsigned &TheIndex) {
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+ unsigned NodeSize = Pool->NodeSize;
+
+ // Search the partially allocated slab list for the slab that contains this
+ // node.
+ int Idx = -1;
+ if (PS) { // Pool->Ptr1 could be null if Ptr2 isn't
+ for (; PS; PS = PS->Next) {
+ Idx = PS->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ }
+ }
+
+ // If the partially allocated slab list doesn't contain it, maybe the
+ // completely allocated list does.
+ if (PS == 0) {
+ PS = (PoolSlab*)Pool->Ptr2;
+ assert(Idx == -1 && "Found node but don't have PS?");
+
+ while (PS) {
+ assert(PS && "poolfree: node being free'd not found in allocation "
+ " pool specified!\n");
+ Idx = PS->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PS = PS->Next;
+ }
+ }
+
+ // Otherwise, maybe its a block within LargeArrays
+ if(PS == 0) {
+ PS = (PoolSlab*)Pool->LargeArrays;
+ assert(Idx == -1 && "Found node but don't have PS?");
+
+ while (PS) {
+ assert(PS && "poolfree: node being free'd not found in allocation "
+ " pool specified!\n");
+ Idx = PS->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PS = PS->Next;
+ }
+ }
+
+ TheIndex = Idx;
+ return PS;
+}
+#endif
+
+void* poolallocatorcheck(PoolTy *Pool, void *Node) {
+ PoolSlab *PS = (PoolSlab*)((unsigned)Node & ~(PageSize-1));
+
+ if (Pool->NumSlabs > AddrArrSize) {
+ hash_set<void*> &theSlabs = *Pool->Slabs;
+ if (theSlabs.find((void*)PS) == theSlabs.end()) {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ int Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ if (Idx != -1) {
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ return PS;
+ break;
+ }
+ PSlab = PSlab->Next;
+ }
+
+ if (Idx == -1) {
+ Splay *ref = splay_find_ptr(Pool->splay, (unsigned long) Node);
+ if (ref) {
+ return 0;
+ }
+ printf("poolcheck1: node being checked not found in pool with right"
+ " alignment\n");
+ abort();
+ } else {
+ return 0;
+ //exit(-1);
+ }
+ } else {
+ // here we check for the splay tree
+ Splay *ref = splay_find_ptr(Pool->splay, (unsigned long) Node);
+ if (ref) {
+ return 0;
+ } else {
+ printf("poolcheck2: ref not found "
+ " alignment\n");
+ abort();
+ exit(-1);
+ }
+ }
+ } else {
+ unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+ if (startaddr > (unsigned long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ abort();
+ }
+ unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+ if (offset != 0) {
+ printf("poolcheck3: node being checked does not have right alignment\n");
+ abort();
+ }
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ return PS;
+ }
+ } else {
+ bool found = false;
+ for (unsigned i = 0; i < AddrArrSize && !found; ++i) {
+ if ((unsigned)Pool->SlabAddressArray[i] == (unsigned) PS) {
+ found = true;
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ }
+ }
+
+ if (found) {
+ // Check that Node does not point to PoolSlab meta-data
+ unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+ if (startaddr > (unsigned long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ exit(-1);
+ }
+ unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+ if (offset != 0) {
+ printf("poolcheck4: node being checked does not have right alignment\n");
+ abort();
+ }
+ return PS;
+ } else {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ int Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ if (Idx != -1) {
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ break;
+ }
+ PSlab = PSlab->Next;
+ }
+ if (Idx == -1) {
+ Splay *ref = splay_find_ptr(Pool->splay, (unsigned long) Node);
+ if (ref) return 0;
+ printf("poolcheck6: node being checked not found in pool with right"
+ " alignment\n");
+ abort();
+ } else {
+ return PSlab;
+ }
+ } else {
+ Splay *ref = splay_find_ptr(Pool->splay, (unsigned long) Node);
+ if (ref) {
+ return 0;
+ } else {
+ printf("poolcheck5: ref not found "
+ " alignment check not done \n");
+ abort();
+ }
+ }
+ }
+ }
+}
+
+/*
+void poolcheckarray(MetaPoolTy **MP, void *NodeSrc, void *NodeResult) {
+ MetaPoolTy *MetaPool = *MP;
+ if (!MetaPool) {
+ printf("Empty meta pool? \n");
+ exit(-1);
+ }
+ //iteratively search through the list
+ //Check if there are other efficient data structures.
+ hash_set<void *>::iterator PTI = MetaPool->PoolTySet->begin(), PTE = MetaPool->PoolTySet->end();
+ PoolTy *srcPool = 0;
+ for (; PTI != PTE; ++PTI) {
+ PoolTy *Pool = (PoolTy *)*PTI;
+ PoolSlab *PS;
+ PS = (PoolSlab*)((unsigned long)NodeSrc & ~(PageSize-1));
+ if (Pool->prevPage[0] == PS) {
+ srcPool = Pool;
+ }
+ if (Pool->prevPage[1] == PS) {
+ srcPool = Pool;
+ }
+ if (Pool->prevPage[2] == PS) {
+ srcPool = Pool;
+ }
+ if (Pool->prevPage[3] == PS) {
+ srcPool = Pool;
+ }
+ if (poolcheckoptim(Pool, NodeSrc)) {
+ srcPool = Pool;
+ } else continue;
+ //Now check for reuslt
+ if (poolcheckoptim(srcPool, NodeResult)) {
+ MetaPool->cachePool = srcPool;
+ return;
+ } else {
+ printf("source and dest belong to different pools\n");
+ exit(-1);
+ }
+ }
+ printf("poolcheck failure \n");
+ exit(-1);
+}
+*/
+
+void poolfree(PoolTy *Pool, void *Node) {
+ assert(Pool && "Null pool pointer passed in to poolfree!\n");
+ DEBUG(printf("poolfree %x %x \n",Pool,Node);)
+ PoolSlab *PS;
+ int Idx;
+ PS = (PoolSlab *)poolallocatorcheck(Pool, Node);
+ assert(PS && "poolfree the element not in pool ");
+ if (PS->isSingleArray) {
+ PS->unlinkFromList();
+ unsigned NumPages = PS->GetNumNodesInSlab() / PageSize;
+
+ unsigned NodesPerSlab = PoolSlab::getSlabSize(Pool);
+
+ unsigned Size = sizeof(PoolSlab) + 4*((NodesPerSlab+15)/16) +
+ Pool->NodeSize* NodesPerSlab;
+ assert(Size <= PageSize && "Trying to allocate a slab larger than a page!");
+ for (unsigned i = 0; i <NumPages; ++i) {
+ PoolSlab *PSi = (PoolSlab *)((unsigned long)PS + i * PageSize);
+
+ PSi->initialize(NodesPerSlab);
+ if (i != 0) {
+ PSi->addToList((PoolSlab**)&Pool->Ptr1);
+ }
+ if (Pool->NumSlabs > AddrArrSize) {
+ DEBUG(printf("new slab inserting %x \n", (void *)New);)
+ Pool->Slabs->insert((void *)PSi);
+ } else if (Pool->NumSlabs == AddrArrSize) {
+ // Create the hash_set
+ Pool->Slabs = new hash_set<void *>;
+ Pool->Slabs->insert((void *)PSi);
+ for (unsigned i = 0; i < AddrArrSize; ++i)
+ Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+ } else {
+ // Insert it in the array
+ Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) PSi;
+ }
+ Pool->NumSlabs++;
+ }
+ return;
+ }
+ Idx = PS->containsElement(Node, Pool->NodeSize);
+ assert((Idx != -1) && " node not present, it should have aborted ");
+
+ // If PS was full, it must have been in list #2. Unlink it and move it to
+ // list #1.
+ if (PS->isFull()) {
+ // Now that we found the node, we are about to free an element from it.
+ // This will make the slab no longer completely full, so we must move it to
+ // the other list!
+ PS->unlinkFromList(); // Remove it from the Ptr2 list.
+
+ PoolSlab **InsertPosPtr = (PoolSlab**)&Pool->Ptr1;
+
+ // If the partially full list has an empty node sitting at the front of the
+ // list, insert right after it.
+ if (*InsertPosPtr && (*InsertPosPtr)->isEmpty())
+ InsertPosPtr = &(*InsertPosPtr)->Next;
+
+ PS->addToList(InsertPosPtr); // Insert it now in the Ptr1 list.
+ }
+
+ // Free the actual element now!
+ PS->freeElement(Idx);
+
+ // Ok, if this slab is empty, we unlink it from the of slabs and either move
+ // it to the head of the list, or free it, depending on whether or not there
+ // is already an empty slab at the head of the list.
+ //
+ if (PS->isEmpty()) {
+ PS->unlinkFromList(); // Unlink from the list of slabs...
+
+ // If we can free this pool, check to see if there are any empty slabs at
+ // the start of this list. If so, delete the FirstSlab!
+ PoolSlab *FirstSlab = (PoolSlab*)Pool->Ptr1;
+ if (0 && FirstSlab && FirstSlab->isEmpty()) {
+ // Here we choose to delete FirstSlab instead of the pool we just freed
+ // from because the pool we just freed from is more likely to be in the
+ // processor cache.
+ FirstSlab->unlinkFromList();
+ FirstSlab->destroy();
+ // Pool->Slabs.erase((void *)FirstSlab);
+ }
+
+ // Link our slab onto the head of the list so that allocations will find it
+ // efficiently.
+ PS->addToList((PoolSlab**)&Pool->Ptr1);
+ }
+}
+
+
+ void *poolrealloc(PoolTy *Pool, void *Node, unsigned NumBytes) {
+ if (Node == 0) return poolalloc(Pool, NumBytes);
+ if (NumBytes == 0) {
+ poolfree(Pool, Node);
+ return 0;
+ }
+ void *New = poolalloc(Pool, NumBytes);
+ // unsigned Size =
+ //FIXME the following may not work in all cases
+ memcpy(New, Node, NumBytes);
+ poolfree(Pool, Node);
+ return New;
+ }
+
+ void poolregister(PoolTy *Pool, void *allocadptr, unsigned NumBytes) {
+ POOLCHECK(poolcheckregister(Pool->splay, allocadptr, NumBytes);)
+ }
+ PoolCheckSlab *poolcheckslab(void *Pool) {
+ return ((PoolTy *)Pool)->PCS;
+ }
+
+ Splay *poolchecksplay(void *Pool) {
+ return ((PoolTy *)Pool)->splay;
+ }
+
+ void poolcheckfail (const char * msg) {
+ fprintf (stderr, msg);
+ fflush (stderr);
+ exit (-1);
+ }
+
+ void * poolcheckmalloc (unsigned int size) {
+ return malloc (size);
+ }
diff --git a/safecode/runtime/KernelSafePoolAllocator/PoolCheck.cpp b/safecode/runtime/KernelSafePoolAllocator/PoolCheck.cpp
new file mode 100755
index 0000000..60fe708
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/PoolCheck.cpp
@@ -0,0 +1,185 @@
+//===- PoolCheck.cpp - Implementation of poolallocator runtime -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is one possible implementation of the LLVM pool allocator runtime
+// library.
+//
+// This uses the 'Ptr1' field to maintain a linked list of slabs that are either
+// empty or are partially allocated from. The 'Ptr2' field of the PoolTy is
+// used to track a linked list of slabs which are full, ie, all elements have
+// been allocated from them.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PoolCheck.h"
+#ifdef LLVA_KERNEL
+#include <stdarg.h>
+#endif
+#define DEBUG(x)
+
+//===----------------------------------------------------------------------===//
+extern unsigned PageSize;
+
+void poolcheckinit(void *Pool, unsigned NodeSize) {
+ //to be called from poolinit
+ //do nothing for now.
+}
+
+// poolcheckdestroy - to be called from pooldestroy
+//
+void poolcheckdestroy(void *Pool) {
+ //Do nothing as of now since all MEtaPools are global
+ // free_splay(Pool->splay);
+}
+
+
+void AddPoolDescToMetaPool(MetaPoolTy **MP, void *P) {
+ MetaPoolTy *MetaPoolPrev = *MP;
+ MetaPoolTy *MetaPool = *MP;
+ if (MetaPool) {
+ MetaPool = MetaPool->next;
+ } else {
+ *MP = (MetaPoolTy *) poolcheckmalloc (sizeof(MetaPoolTy));
+ (*MP)->Pool = P;
+ (*MP)->next = 0;
+ return;
+ }
+ while (MetaPool) {
+ MetaPool = MetaPool->next;
+ MetaPoolPrev = MetaPool;
+ }
+ //MetaPool is null;
+ MetaPoolPrev->next = (MetaPoolTy *) poolcheckmalloc (sizeof(MetaPoolTy));
+ MetaPoolPrev->next->Pool = P;
+ MetaPoolPrev->next->next = 0;
+}
+
+
+bool poolcheckoptim(void *Pool, void *Node) {
+ //PageSize needs to be modified accordingly
+ void *PS = (void *)((unsigned)Node & ~(PageSize-1));
+ PoolCheckSlab * PCS = poolcheckslab(Pool);
+ while (PCS) {
+ if (PCS->Slab == PS) return true;
+ //we can optimize by moving it to the front of the list
+ PCS = PCS->nextSlab;
+ }
+ // here we check for the splay tree
+ Splay *psplay = poolchecksplay(Pool);
+ Splay *ref = splay_find_ptr(psplay, (unsigned long) Node);
+ if (ref) {
+ return true;
+ }
+ return false;
+}
+
+
+inline bool refcheck(Splay *splay, void *Node) {
+ unsigned long base = (unsigned long) (splay->key);
+ unsigned long length = (unsigned long) (splay->val);
+ unsigned long result = (unsigned long) Node;
+ if ((result >= base) && (result < (base + length))) return true;
+ return false;
+
+}
+
+
+bool poolcheckarrayoptim(void *Pool, void *NodeSrc, void *NodeResult) {
+ Splay *psplay = poolchecksplay(Pool);
+ splay *ref = splay_find_ptr(psplay, (unsigned long)NodeSrc);
+ if (ref) {
+ return refcheck(ref, NodeResult);
+ }
+ return false;
+}
+
+void poolcheckarray(MetaPoolTy **MP, void *NodeSrc, void *NodeResult) {
+ MetaPoolTy *MetaPool = *MP;
+ if (!MetaPool) {
+ poolcheckfail ("Empty meta pool? \n");
+ }
+ //iteratively search through the list
+ //Check if there are other efficient data structures.
+ while (MetaPool) {
+ void *Pool = MetaPool->Pool;
+ if (poolcheckarrayoptim(Pool, NodeSrc, NodeResult)) return ;
+ MetaPool = MetaPool->next;
+ }
+ poolcheckfail ("poolcheck failure \n");
+}
+
+void poolcheck(MetaPoolTy **MP, void *Node) {
+ MetaPoolTy *MetaPool = *MP;
+ if (!MetaPool) {
+ poolcheckfail ("Empty meta pool? \n");
+ }
+ // iteratively search through the list
+ //Check if there are other efficient data structures.
+
+ while (MetaPool) {
+ void *Pool = MetaPool->Pool;
+ if (poolcheckoptim(Pool, Node)) return;
+ MetaPool = MetaPool->next;
+ }
+ poolcheckfail ("poolcheck failure \n");
+}
+
+
+void poolcheckAddSlab(PoolCheckSlab **PCSPtr, void *Slab) {
+ PoolCheckSlab *PCSPrev = *PCSPtr;
+ PoolCheckSlab *PCS = *PCSPtr;
+ if (PCS) {
+ PCS = PCS->nextSlab;
+ } else {
+ *PCSPtr = (PoolCheckSlab *) poolcheckmalloc (sizeof(PoolCheckSlab));
+ (*PCSPtr)->Slab = Slab;
+ (*PCSPtr)->nextSlab = 0;
+ return;
+ }
+ while (PCS) {
+ PCS = PCS->nextSlab;
+ PCSPrev = PCS;
+ }
+ //PCS is null;
+ PCSPrev->nextSlab = (PoolCheckSlab *) poolcheckmalloc (sizeof(PoolCheckSlab));
+ PCSPrev->nextSlab->Slab = Slab;
+ PCSPrev->nextSlab->nextSlab = 0;
+}
+
+
+ void exactcheck(int a, int b) {
+ if ((0 > a) || (a >= b)) {
+ poolcheckfail ("exact check failed\n");
+ }
+ }
+
+ //
+ // Disable this for kernel code. I'm not sure how kernel code handles
+ // va_list type functions.
+ //
+#ifdef LLVA_KERNEL
+ void funccheck(unsigned num, void *f, void *g, ...) {
+ va_list ap;
+ unsigned i = 0;
+ if (f == g) return;
+ i++;
+ va_start(ap, g);
+ for ( ; i != num; ++i) {
+ void *h = va_arg(ap, void *);
+ if (f == h) {
+ return;
+ }
+ }
+ abort();
+ }
+#endif
+
+ void poolcheckregister(Splay *splay, void * allocaptr, unsigned NumBytes) {
+ splay_insert_ptr(splay, (unsigned long)(allocaptr), NumBytes);
+ }
diff --git a/safecode/runtime/KernelSafePoolAllocator/PoolCheck.h b/safecode/runtime/KernelSafePoolAllocator/PoolCheck.h
new file mode 100755
index 0000000..a193502
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/PoolCheck.h
@@ -0,0 +1,55 @@
+//===- PoolAllocator.h - Pool allocator runtime interface file --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface which is implemented by the LLVM pool
+// allocator runtime library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POOLCHECK_RUNTIME_H
+#define POOLCHECK_RUNTIME_H
+
+#include "splay.h"
+
+typedef struct PoolCheckSlab {
+ void *Slab;
+ PoolCheckSlab *nextSlab;
+} PoolCheckSlab;
+
+typedef struct MetaPoolTy {
+ void * Pool;
+ MetaPoolTy *next;
+} MetaPoolTy;
+
+
+#ifdef __cpluscplus
+extern "C" {
+#endif
+ //register that starting from allocaptr numbytes are a part of the pool
+ void poolcheck(MetaPoolTy **Pool, void *Node);
+ bool poolcheckoptim(void *Pool, void *Node);
+ void poolcheckregister(Splay *splay, void * allocaptr, unsigned NumBytes);
+ void AddPoolDescToMetaPool(void **MetaPool, void *PoolDesc);
+ void poolcheckarray(MetaPoolTy *Pool, void *Node, void * Node1);
+ bool poolcheckarrayoptim(MetaPoolTy *Pool, void *Node, void * Node1);
+ void poolcheckAddSlab(PoolCheckSlab **PoolCheckSlabPtr, void *Slab);
+ void poolcheckinit(void *Pool, unsigned NodeSize);
+ void poolcheckdestroy(void *Pool);
+ void poolcheckfree(void *Pool, void *Node);
+
+ // Functions that need to be provided by the pool allocation run-time
+ PoolCheckSlab *poolcheckslab(void *Pool);
+ Splay *poolchecksplay(void *Pool);
+ void poolcheckfail (const char * msg);
+ void * poolcheckmalloc (unsigned int size);
+#ifdef __cpluscplus
+}
+#endif
+
+#endif
diff --git a/safecode/runtime/KernelSafePoolAllocator/README b/safecode/runtime/KernelSafePoolAllocator/README
new file mode 100755
index 0000000..f6210a3
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/README
@@ -0,0 +1,13 @@
+* 0. Add "#include poolcheck.h" in the kernel pool allocator runtime
+1. You need to add statements corresponding to those within POOLCHECKINSERT macro in PoolAllocatorBitMask.cpp in to the kernel allocator
+2. Replace malloc with kmalloc equivalent in poolcheck.cpp
+* 3. Do not allow the poolallocator to release memory to the system
+4. PoolCheck.cpp uses PageSize defined in PoolAllocatorBitMask.cpp , you need to adjust it to Slab Size in the kernel pool allocator
+5. Add two functions to return splay tree and poolcheckslab in PoolAllocator.h
+
+System functions/features that poolcheck library depends upon:
+
+1. memory allocation function (malloc/kmalloc)
+2. function to call if run-time checks fail
+3. function to call if splay tree code fails
+
diff --git a/safecode/runtime/KernelSafePoolAllocator/splay.cpp b/safecode/runtime/KernelSafePoolAllocator/splay.cpp
new file mode 100755
index 0000000..dc71e9e
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/splay.cpp
@@ -0,0 +1,322 @@
+// Note: This file is obtained from
+// http://www.cs.utk.edu/~cs140/spring-2005/notes/Splay/
+// FIXME: This may not be the most efficient version of splay implementation
+// This may be updated with a different splay implementation in near future
+#include <stdio.h>
+#include "splay.h"
+#include <stdlib.h>
+void rotate(Splay *node)
+{
+ Splay *parent, *grandparent;
+
+ if (node->parent->is_sentinel) return;
+
+ parent = node->parent;
+ grandparent = parent->parent;
+
+ if (parent->left == node) {
+ parent->left = node->right;
+ if (parent->left != NULL) parent->left->parent = parent;
+ node->right = parent;
+ } else if (parent->right == node) {
+ parent->right = node->left;
+ if (parent->right != NULL) parent->right->parent = parent;
+ node->left = parent;
+ } else {
+ fprintf(stderr, "rotate: error: parent's children are not right\n");
+ exit(1);
+ }
+
+ parent->parent = node;
+ node->parent = grandparent;
+
+ if (grandparent->is_sentinel) {
+ grandparent->parent = node;
+ } else if (grandparent->left == parent) {
+ grandparent->left = node;
+ } else if (grandparent->right == parent) {
+ grandparent->right = node;
+ } else {
+ fprintf(stderr, "rotate: error: grandparent's children are not right\n");
+ exit(1);
+ }
+}
+
+ void splay(Splay *node)
+{
+ Splay *parent, *grandparent;
+
+ if (node->is_sentinel) return;
+
+ while(1) {
+ if (node->parent->is_sentinel) return;
+
+ parent = node->parent;
+ grandparent = parent->parent;
+
+ /* If the node's parent is the root of the tree, do one rotation */
+
+ if (grandparent->is_sentinel) {
+ rotate(node);
+
+ /* If we have a zig-zig, then rotate my parent, then rotate me */
+
+ } else if ((parent->left == node && grandparent->left == parent) ||
+ (parent->right == node && grandparent->right == parent)) {
+ rotate(parent);
+ rotate(node);
+
+ /* If we have a zig-zag, then rotate me twice */
+
+ } else {
+ rotate(node);
+ rotate(node);
+ }
+ }
+}
+
+Splay *new_splay()
+{
+ Splay *tree;
+
+ tree = (Splay *) malloc(sizeof(struct splay));
+ tree->key = 0;
+ tree->val = 0;
+ tree->is_sentinel = 1;
+ tree->flink = tree;
+ tree->blink = tree;
+ tree->left = NULL;
+ tree->right = NULL;
+ tree->parent = NULL;
+ return tree;
+}
+
+Splay *splay_root(Splay *tree)
+{
+ return tree->parent;
+}
+
+Splay *splay_first(Splay *tree)
+{
+ return tree->flink;
+}
+
+Splay *splay_last(Splay *tree)
+{
+ return tree->blink;
+}
+
+Splay *splay_next(Splay *node)
+{
+ return node->flink;
+}
+
+Splay *splay_prev(Splay *node)
+{
+ return node->blink;
+}
+
+Splay *splay_nil(Splay *tree)
+{
+ return tree;
+}
+
+void free_splay(Splay *tree)
+{
+ Splay *ptr;
+
+ while (1) {
+ ptr = splay_first(tree);
+ if (!ptr->is_sentinel) {
+ splay_delete_node(ptr);
+ } else {
+ free(ptr);
+ return;
+ }
+ }
+}
+
+ Splay *splay_find_nearest_ptr(Splay *tree, unsigned long key, int *cmpval)
+{
+ Splay *s, *last;
+ int cmp;
+
+ last = tree;
+ s = splay_root(tree);
+ cmp = 1;
+
+ while(s != NULL) {
+ last = s;
+ if (key == s->key) {
+ *cmpval = 0;
+ return s;
+ } else if (key < (s->key)) {
+ s = s->left;
+ cmp = -1;
+ } else {
+ if (key < (s->val + s->key)) {
+ *cmpval = 0;
+ return s;
+ }
+ s = s->right;
+ cmp = 1;
+ }
+ }
+
+ *cmpval = cmp;
+ return last;
+}
+
+
+Splay *splay_find_ptr(Splay *tree, unsigned long key)
+{
+ int cmpval;
+ Splay *s;
+
+ s = splay_find_nearest_ptr(tree, key, &cmpval);
+ splay(s);
+ if (cmpval == 0) return s; else return NULL;
+}
+
+
+Splay *splay_insert(Splay *tree, Jval key, Jval val, Splay *parent, int cmpval)
+{
+ Splay *s;
+
+ s = (Splay *) malloc(sizeof(struct splay));
+ s->is_sentinel = 0;
+ s->parent = parent;
+ s->left = NULL;
+ s->right = NULL;
+ s->key = key;
+ s->val = val;
+
+ /* Set the parent's correct child pointer. The only
+ subtle case here is when the key is already in
+ the tree -- then we need to find a leaf node
+ to use as a parent */
+
+ /* When we're done here, parent should point to the
+ new node's successor in the linked list */
+
+ if (parent->is_sentinel) {
+ parent->parent = s;
+ } else {
+ if (cmpval == 0) { /* If the key is already in the
+ tree, try to insert a new one as the
+ node's right child. If the node already
+ has a right child, then try to insert the
+ new one as a left child. If there is already
+ a left child, then go to parent-flink and
+ insert the node as its left child. */
+ if (parent->right == NULL) {
+ cmpval = 1;
+ } else if (parent->left == NULL) {
+ cmpval = -1;
+ } else {
+ parent = parent->flink;
+ s->parent = parent;
+ cmpval = -1;
+ }
+ }
+ if (cmpval > 0) { /* Insert as right child */
+ if (parent->right != NULL) {
+ fprintf(stderr, "splay_insert error: parent->right != NULL");
+ exit(1);
+ }
+ parent->right = s;
+ parent = parent->flink;
+ } else {
+ if (parent->left != NULL) {
+ fprintf(stderr, "splay_insert error: parent->left != NULL");
+ exit(1);
+ }
+ parent->left = s;
+ }
+ }
+
+ s->flink = parent;
+ s->blink = parent->blink;
+ s->flink->blink = s;
+ s->blink->flink = s;
+ splay(s);
+ return s;
+}
+
+Splay *splay_insert_ptr(Splay *tree, unsigned long key, Jval val)
+{
+ Splay *parent;
+ int cmpval;
+
+ parent = splay_find_nearest_ptr(tree, key, &cmpval);
+ return splay_insert(tree, key, val, parent, cmpval);
+}
+
+extern void splay_delete_node(Splay *node)
+{
+ Splay *left, *right, *tree, *newroot;
+
+ splay(node);
+
+ tree = node->parent;
+
+ left = node->left;
+ right = node->right;
+ newroot = node->flink;
+
+ node->flink->blink = node->blink;
+ node->blink->flink = node->flink;
+
+ free(node);
+
+ if (right == NULL && left == NULL) {
+ tree->parent = NULL;
+ } else if (right == NULL) {
+ tree->parent = left;
+ left->parent = tree;
+ } else if (left == NULL) {
+ tree->parent = right;
+ right->parent = tree;
+ } else {
+ tree->parent = right;
+ right->parent = tree;
+ splay(newroot);
+ newroot->left = left;
+ left->parent = newroot;
+ }
+}
+ Splay *finish_gte(int cmpval, Splay *s, int *found)
+{
+
+ if (cmpval == 0) {
+ *found = 1;
+ return s;
+ } else if (cmpval < 0) {
+ *found = 0;
+ return s;
+ } else {
+ *found = 1;
+ return s->flink;
+ }
+}
+/*
+Splay *splay_find_gte_str(Splay *tree, char *key, int *found)
+{
+ int cmpval;
+ Splay *s;
+
+ s = splay_find_nearest_str(tree, key, &cmpval);
+ return finish_gte(cmpval, s, found);
+}
+*/
+
+Splay *splay_find_gte_ptr(Splay *tree, unsigned long key, int *found)
+{
+ int cmpval;
+ Splay *s;
+
+ s = splay_find_nearest_ptr(tree, key, &cmpval);
+ return finish_gte(cmpval, s, found);
+}
+
+
diff --git a/safecode/runtime/KernelSafePoolAllocator/splay.h b/safecode/runtime/KernelSafePoolAllocator/splay.h
new file mode 100755
index 0000000..6ec89c0
--- /dev/null
+++ b/safecode/runtime/KernelSafePoolAllocator/splay.h
@@ -0,0 +1,53 @@
+// Note: This file is obtained from
+// http://www.cs.utk.edu/~cs140/spring-2005/notes/Splay/
+// FIXME: This may not be the most efficient version of splay implementation
+// This may be updated with a different splay implementation in near future
+
+#ifndef _SPLAY_
+#define _SPLAY_
+
+typedef unsigned long Jval ;
+
+/* Node identities */
+
+#define SPLAY_SENTINEL 0
+#define SPLAY_OTHER 1
+
+typedef struct splay {
+ Jval key;
+ Jval val;
+ int is_sentinel;
+ struct splay *left;
+ struct splay *right;
+ struct splay *flink;
+ struct splay *blink;
+ struct splay *parent;
+} Splay;
+
+#ifdef __cpluscplus
+extern "C" {
+#endif
+ Splay *new_splay();
+ void free_splay(Splay *);
+ Splay *splay_insert_ptr(Splay *tree, unsigned long key, Jval val);
+ Splay *splay_find_ptr(Splay *tree, unsigned long key);
+ Splay *splay_find_gte_ptr(Splay *tree, unsigned long key, int *found);
+
+ Splay *splay_root(Splay *tree);
+ Splay *splay_first(Splay *tree);
+ Splay *splay_last(Splay *tree);
+ Splay *splay_next(Splay *node);
+ Splay *splay_prev(Splay *node);
+ Splay *splay_nil(Splay *tree);
+
+ void splay_delete_node(Splay *node);
+#ifdef __cpluscplus
+}
+#endif
+
+#define splay_traverse(ptr, list) \
+ for (ptr = splay_first(list); ptr != splay_nil(list); ptr = splay_next(ptr))
+#define splay_rtraverse(ptr, list) \
+ for (ptr = splay_last(list); ptr != splay_nil(list); ptr = splay_prev(ptr))
+
+#endif
diff --git a/safecode/runtime/Makefile b/safecode/runtime/Makefile
new file mode 100755
index 0000000..73aa89b
--- /dev/null
+++ b/safecode/runtime/Makefile
@@ -0,0 +1,12 @@
+#
+# Relative path to the top of the source tree.
+#
+LEVEL=..
+
+#
+# List all of the subdirectories that we will compile.
+#
+PARALLEL_DIRS=SafePoolAllocator BoundsCheckAllocator KernelSafePoolAllocator
+
+
+include $(LEVEL)/Makefile.common
diff --git a/safecode/runtime/SafePoolAllocator/Makefile b/safecode/runtime/SafePoolAllocator/Makefile
new file mode 100755
index 0000000..7e8ddd9
--- /dev/null
+++ b/safecode/runtime/SafePoolAllocator/Makefile
@@ -0,0 +1,9 @@
+LEVEL = ../..
+BYTECODE_LIBRARY=1
+SHARED_LIBRARY=1
+LIBRARYNAME=poolalloc_safe_rt
+
+include $(LEVEL)/Makefile.common
+
+# Always build optimized and debug versions
+all:: $(LIBNAME_OBJO) $(LIBNAME_OBJG)
diff --git a/safecode/runtime/SafePoolAllocator/PageManager.cpp b/safecode/runtime/SafePoolAllocator/PageManager.cpp
new file mode 100755
index 0000000..cdf549d
--- /dev/null
+++ b/safecode/runtime/SafePoolAllocator/PageManager.cpp
@@ -0,0 +1,128 @@
+//===- PageManager.cpp - Implementation of the page allocator -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PageManager.h interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PageManager.h"
+#ifndef _POSIX_MAPPED_FILES
+#define _POSIX_MAPPED_FILES
+#endif
+#include <unistd.h>
+#include "poolalloc/Support/MallocAllocator.h"
+#include "poolalloc/MMAPSupport.h"
+#include <iostream>
+#include <vector>
+#include <cassert>
+// Define this if we want to use memalign instead of mmap to get pages.
+// Empirically, this slows down the pool allocator a LOT.
+#define USE_MEMALIGN 0
+extern "C" {
+unsigned PageSize = 0;
+}
+extern unsigned poolmemusage;
+void InitializePageManager() {
+ if (!PageSize) {
+ PageSize = 32 * sysconf(_SC_PAGESIZE) ;
+ }
+}
+
+#if !USE_MEMALIGN
+static void *GetPages(unsigned NumPages) {
+#if defined(i386) || defined(__i386__) || defined(__x86__)
+ /* Linux and *BSD tend to have these flags named differently. */
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+# define MAP_ANONYMOUS MAP_ANON
+#endif /* defined(MAP_ANON) && !defined(MAP_ANONYMOUS) */
+#elif defined(sparc) || defined(__sparc__) || defined(__sparcv9)
+ /* nothing */
+#else
+ std::cerr << "This architecture is not supported by the pool allocator!\n";
+ abort();
+#endif
+
+#if defined(__linux__)
+#define fd 0
+#else
+#define fd -1
+#endif
+ void *Addr;
+ //MMAP DOESNOT WORK !!!!!!!!
+ // Addr = mmap(0, NumPages*PageSize, PROT_READ|PROT_WRITE,
+ // MAP_SHARED|MAP_ANONYMOUS, fd, 0);
+ // void *pa = malloc(NumPages * PageSize);
+ // assert(Addr != MAP_FAILED && "MMAP FAILED!");
+ if (posix_memalign(&Addr, PageSize, NumPages*PageSize) != 0){
+ assert(1 && "memalign failed \n");
+ }
+ poolmemusage += NumPages * PageSize;
+ memset(Addr, 0xcc, NumPages *PageSize);
+ return Addr;
+}
+#endif
+
+// Explicitly use the malloc allocator here, to avoid depending on the C++
+// runtime library.
+typedef std::vector<void*, llvm::MallocAllocator<void*> > FreePagesListType;
+
+static FreePagesListType &getFreePageList() {
+ static FreePagesListType *FreePages = 0;
+
+ if (!FreePages) {
+ // Avoid using operator new!
+ FreePages = (FreePagesListType*)malloc(sizeof(FreePagesListType));
+ // Use placement new now.
+ // new (FreePages) std::vector<void*, llvm::MallocAllocator<void*> >();
+ }
+ return *FreePages;
+}
+
+/// AllocatePage - This function returns a chunk of memory with size and
+/// alignment specified by PageSize.
+void *AllocatePage() {
+
+ FreePagesListType &FPL = getFreePageList();
+
+ if (!FPL.empty()) {
+ void *Result = FPL.back();
+ FPL.pop_back();
+ return Result;
+ }
+
+ // Allocate several pages, and put the extras on the freelist...
+ unsigned NumToAllocate = 8;
+ char *Ptr = (char*)GetPages(NumToAllocate);
+
+ for (unsigned i = 1; i != NumToAllocate; ++i)
+ FPL.push_back(Ptr+i*PageSize);
+ return Ptr;
+}
+
+void *AllocateNPages(unsigned Num) {
+ if (Num <= 1) return AllocatePage();
+ return GetPages(Num);
+}
+
+/// FreePage - This function returns the specified page to the pagemanager for
+/// future allocation.
+#define THRESHOLD 5
+void FreePage(void *Page) {
+ FreePagesListType &FPL = getFreePageList();
+ FPL.push_back(Page);
+ //munmap(Page, 1);
+ /*
+ if (FPL.size() > THRESHOLD) {
+ // printf( "pool allocator : reached a threshold \n");
+ // exit(-1);
+ munmap(Page, PageSize);
+ poolmemusage -= PageSize;
+ }
+ */
+}
diff --git a/safecode/runtime/SafePoolAllocator/PageManager.h b/safecode/runtime/SafePoolAllocator/PageManager.h
new file mode 100755
index 0000000..ec57652
--- /dev/null
+++ b/safecode/runtime/SafePoolAllocator/PageManager.h
@@ -0,0 +1,40 @@
+//===- PageManager.h - Allocates memory on page boundaries ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface used by the pool allocator to allocate memory
+// on large alignment boundaries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PAGEMANAGER_H
+#define PAGEMANAGER_H
+
+/// InitializePageManager - This function must be called before any other page
+/// manager accesses are performed. It may be called multiple times.
+///
+void InitializePageManager();
+
+/// PageSize - Contains the size of the unit of memory allocated by
+/// AllocatePage. This is a value that is typically several kilobytes in size,
+/// and is guaranteed to be a power of two.
+///
+extern unsigned PageSize;
+
+/// AllocatePage - This function returns a chunk of memory with size and
+/// alignment specified by getPageSize().
+void *AllocatePage();
+
+/// AllocateNPages -
+void *AllocateNPages(unsigned Num);
+
+/// FreePage - This function returns the specified page to the pagemanager for
+/// future allocation.
+void FreePage(void *Page);
+
+#endif
diff --git a/safecode/runtime/SafePoolAllocator/PoolAllocator.h b/safecode/runtime/SafePoolAllocator/PoolAllocator.h
new file mode 100755
index 0000000..6f59235
--- /dev/null
+++ b/safecode/runtime/SafePoolAllocator/PoolAllocator.h
@@ -0,0 +1,79 @@
+//===- PoolAllocator.h - Pool allocator runtime interface file --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface which is implemented by the LLVM pool
+// allocator runtime library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POOLALLOCATOR_RUNTIME_H
+#define POOLALLOCATOR_RUNTIME_H
+#include "llvm/ADT/hash_set"
+
+#define AddrArrSize 2
+unsigned poolmemusage = 0;
+unsigned PCheckPassed = 1;
+typedef struct PoolTy {
+ // Ptr1, Ptr2 - Implementation specified data pointers.
+ void *Ptr1, *Ptr2;
+
+ // NodeSize - Keep track of the object size tracked by this pool
+ unsigned short NodeSize;
+
+ // FreeablePool - Set to false if the memory from this pool cannot be freed
+ // before destroy.
+ //
+ // unsigned short FreeablePool;
+
+ // Use the hash_set only if the number of Slabs exceeds AddrArrSize
+ hash_set<void*> *Slabs;
+
+ // The array containing the initial address of slabs (as long as there are
+ // fewer than a certain number of them)
+ unsigned SlabAddressArray[AddrArrSize];
+
+ // The number of slabs allocated. Large arrays are not counted
+ unsigned NumSlabs;
+
+ // Large arrays. In SAFECode, these are currently not freed or reused.
+ // A better implementation could split them up into single slabs for reuse,
+ // upon being freed.
+ void *LargeArrays;
+
+ void *prevPage[4];
+ unsigned short lastUsed;
+
+ short AllocadPool;
+ void *allocaptr;
+
+} PoolTy;
+
+extern "C" {
+ void exactcheck(int a, int b) {
+ if ((0 > a) || (a >= b)) {
+ fprintf(stderr, "exact check failed\n");
+ exit(-1);
+ }
+ }
+ void poolinit(PoolTy *Pool, unsigned NodeSize);
+ void poolmakeunfreeable(PoolTy *Pool);
+ void pooldestroy(PoolTy *Pool);
+ void *poolalloc(PoolTy *Pool, unsigned NumBytes);
+ void poolregister(PoolTy *Pool, unsigned NumBytes, void *allocaptr);
+ void poolfree(PoolTy *Pool, void *Node);
+ void poolcheck(PoolTy *Pool, void *Node);
+ void poolcheckoptim(PoolTy *Pool, void *Node);
+ void poolstats() {
+ fprintf(stderr, "pool mem usage %d\n",poolmemusage);
+ }
+ void poolcheckalign(PoolTy *Pool, void *Node, unsigned StartOffset,
+ unsigned EndOffset);
+}
+
+#endif
diff --git a/safecode/runtime/SafePoolAllocator/PoolAllocatorBitMask.cpp b/safecode/runtime/SafePoolAllocator/PoolAllocatorBitMask.cpp
new file mode 100755
index 0000000..4790405
--- /dev/null
+++ b/safecode/runtime/SafePoolAllocator/PoolAllocatorBitMask.cpp
@@ -0,0 +1,1219 @@
+//===- PoolAllocatorBitMask.cpp - Implementation of poolallocator runtime -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is one possible implementation of the LLVM pool allocator runtime
+// library.
+//
+// This uses the 'Ptr1' field to maintain a linked list of slabs that are either
+// empty or are partially allocated from. The 'Ptr2' field of the PoolTy is
+// used to track a linked list of slabs which are full, ie, all elements have
+// been allocated from them.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PoolAllocator.h"
+#include "PageManager.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#define DEBUG(x)
+//===----------------------------------------------------------------------===//
+//
+// PoolSlab implementation
+//
+//===----------------------------------------------------------------------===//
+
+
+// PoolSlab Structure - Hold multiple objects of the current node type.
+// Invariants: FirstUnused <= UsedEnd
+//
+struct PoolSlab {
+ PoolSlab **PrevPtr, *Next;
+ bool isSingleArray; // If this slab is used for exactly one array
+
+private:
+ // FirstUnused - First empty node in slab
+ unsigned short FirstUnused;
+
+ // UsedBegin - The first node in the slab that is used.
+ unsigned short UsedBegin;
+
+ // UsedEnd - 1 past the last allocated node in slab. 0 if slab is empty
+ unsigned short UsedEnd;
+
+ // NumNodesInSlab - This contains the number of nodes in this slab, which
+ // effects the size of the NodeFlags vector, and indicates the number of nodes
+ // which are in the slab.
+ unsigned int NumNodesInSlab;
+
+ // NodeFlagsVector - This array contains two bits for each node in this pool
+ // slab. The first (low address) bit indicates whether this node has been
+ // allocated, and the second (next higher) bit indicates whether this is the
+ // start of an allocation.
+ //
+ // This is a variable sized array, which has 2*NumNodesInSlab bits (rounded up
+ // to 4 bytes).
+ unsigned NodeFlagsVector[1];
+
+ bool isNodeAllocated(unsigned NodeNum) {
+ return NodeFlagsVector[NodeNum/16] & (1 << (NodeNum & 15));
+ }
+
+ void markNodeAllocated(unsigned NodeNum) {
+ NodeFlagsVector[NodeNum/16] |= 1 << (NodeNum & 15);
+ }
+
+ void markNodeFree(unsigned NodeNum) {
+ NodeFlagsVector[NodeNum/16] &= ~(1 << (NodeNum & 15));
+ }
+
+ void setStartBit(unsigned NodeNum) {
+ NodeFlagsVector[NodeNum/16] |= 1 << ((NodeNum & 15)+16);
+ }
+
+ bool isStartOfAllocation(unsigned NodeNum) {
+ return NodeFlagsVector[NodeNum/16] & (1 << ((NodeNum & 15)+16));
+ }
+
+ void clearStartBit(unsigned NodeNum) {
+ NodeFlagsVector[NodeNum/16] &= ~(1 << ((NodeNum & 15)+16));
+ }
+
+public:
+ // create - Create a new (empty) slab and add it to the end of the Pools list.
+ static PoolSlab *create(PoolTy *Pool);
+
+ // createSingleArray - Create a slab for a large singlearray with NumNodes
+ // entries in it, returning the pointer into the pool directly.
+ static void *createSingleArray(PoolTy *Pool, unsigned NumNodes);
+
+ // getSlabSize - Return the number of nodes that each slab should contain.
+ static unsigned getSlabSize(PoolTy *Pool) {
+ // We need space for the header...
+ unsigned NumNodes = PageSize-sizeof(PoolSlab);
+
+ // We need space for the NodeFlags...
+ unsigned NodeFlagsBytes = NumNodes/Pool->NodeSize * 2 / 8;
+ NumNodes -= (NodeFlagsBytes+3) & ~3; // Round up to int boundaries.
+
+ // Divide the remainder among the nodes!
+ return NumNodes / Pool->NodeSize;
+ }
+
+ void addToList(PoolSlab **PrevPtrPtr) {
+ PoolSlab *InsertBefore = *PrevPtrPtr;
+ *PrevPtrPtr = this;
+ PrevPtr = PrevPtrPtr;
+ Next = InsertBefore;
+ if (InsertBefore) InsertBefore->PrevPtr = &Next;
+ }
+
+ void unlinkFromList() {
+ *PrevPtr = Next;
+ if (Next) Next->PrevPtr = PrevPtr;
+ }
+
+ unsigned getSlabSize() const {
+ return NumNodesInSlab;
+ }
+
+ // destroy - Release the memory for the current object.
+ void destroy();
+
+ // isEmpty - This is a quick check to see if this slab is completely empty or
+ // not.
+ bool isEmpty() const { return UsedEnd == 0; }
+
+ // isFull - This is a quick check to see if the slab is completely allocated.
+ //
+ bool isFull() const { return isSingleArray || FirstUnused == getSlabSize(); }
+
+ // allocateSingle - Allocate a single element from this pool, returning -1 if
+ // there is no space.
+ int allocateSingle();
+
+ // allocateMultiple - Allocate multiple contiguous elements from this pool,
+ // returning -1 if there is no space.
+ int allocateMultiple(unsigned Num);
+
+ // getElementAddress - Return the address of the specified element.
+ void *getElementAddress(unsigned ElementNum, unsigned ElementSize) {
+ char *Data = (char*)&NodeFlagsVector[((unsigned)NumNodesInSlab+15)/16];
+ return &Data[ElementNum*ElementSize];
+ }
+ const void *getElementAddress(unsigned ElementNum, unsigned ElementSize)const{
+ const char *Data =
+ (const char *)&NodeFlagsVector[(unsigned)(NumNodesInSlab+15)/16];
+ return &Data[ElementNum*ElementSize];
+ }
+
+ // containsElement - Return the element number of the specified address in
+ // this slab. If the address is not in slab, return -1.
+ int containsElement(void *Ptr, unsigned ElementSize) const;
+
+ // freeElement - Free the single node, small array, or entire array indicated.
+ void freeElement(unsigned short ElementIdx);
+
+ // lastNodeAllocated - Return one past the last node in the pool which is
+ // before ScanIdx, that is allocated. If there are no allocated nodes in this
+ // slab before ScanIdx, return 0.
+ unsigned lastNodeAllocated(unsigned ScanIdx);
+};
+
+// create - Create a new (empty) slab and add it to the end of the Pools list.
+PoolSlab *PoolSlab::create(PoolTy *Pool) {
+ unsigned NodesPerSlab = getSlabSize(Pool);
+
+ unsigned Size = sizeof(PoolSlab) + 4*((NodesPerSlab+15)/16) +
+ Pool->NodeSize*getSlabSize(Pool);
+ assert(Size <= PageSize && "Trying to allocate a slab larger than a page!");
+ PoolSlab *PS = (PoolSlab*)AllocatePage();
+
+ PS->NumNodesInSlab = NodesPerSlab;
+ PS->isSingleArray = 0; // Not a single array!
+ PS->FirstUnused = 0; // Nothing allocated.
+ PS->UsedBegin = 0; // Nothing allocated.
+ PS->UsedEnd = 0; // Nothing allocated.
+
+ // Add the slab to the list...
+ PS->addToList((PoolSlab**)&Pool->Ptr1);
+ // printf(" creating a slab %x\n", PS);
+ return PS;
+}
+
+void *PoolSlab::createSingleArray(PoolTy *Pool, unsigned NumNodes) {
+ // FIXME: This wastes memory by allocating space for the NodeFlagsVector
+ unsigned NodesPerSlab = getSlabSize(Pool);
+ assert(NumNodes > NodesPerSlab && "No need to create a single array!");
+
+ unsigned NumPages = (NumNodes+NodesPerSlab-1)/NodesPerSlab;
+ PoolSlab *PS = (PoolSlab*)AllocateNPages(NumPages);
+
+ assert(PS && "poolalloc: Could not allocate memory!");
+
+ if (Pool->NumSlabs > AddrArrSize)
+ Pool->Slabs->insert((void*)PS);
+ else if (Pool->NumSlabs == AddrArrSize) {
+ // Create the hash_set
+ Pool->Slabs = new hash_set<void *>;
+ Pool->Slabs->insert((void *)PS);
+ for (unsigned i = 0; i < AddrArrSize; ++i)
+ Pool->Slabs->insert((void *) Pool->SlabAddressArray[i]);
+ } else {
+ // Insert it in the array
+ Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) PS;
+ }
+ Pool->NumSlabs++;
+
+ PS->addToList((PoolSlab**)&Pool->LargeArrays);
+
+ PS->isSingleArray = 1;
+ PS->NumNodesInSlab = NumPages * PageSize;
+ *(unsigned*)&PS->FirstUnused = NumPages;
+ return PS->getElementAddress(0, 0);
+}
+
+void PoolSlab::destroy() {
+ if (isSingleArray)
+ for (unsigned NumPages = *(unsigned*)&FirstUnused; NumPages != 1;--NumPages)
+ FreePage((char*)this + (NumPages-1)*PageSize);
+
+ FreePage(this);
+}
+
+// allocateSingle - Allocate a single element from this pool, returning -1 if
+// there is no space.
+int PoolSlab::allocateSingle() {
+ // If the slab is a single array, go on to the next slab. Don't allocate
+ // single nodes in a SingleArray slab.
+ if (isSingleArray) return -1;
+
+ unsigned SlabSize = getSlabSize();
+
+ // Check to see if there are empty entries at the end of the slab...
+ if (UsedEnd < SlabSize) {
+ // Mark the returned entry used
+ unsigned short UE = UsedEnd;
+ markNodeAllocated(UE);
+ setStartBit(UE);
+
+ // If we are allocating out the first unused field, bump its index also
+ if (FirstUnused == UE)
+ FirstUnused++;
+
+ // Return the entry, increment UsedEnd field.
+ return UsedEnd++;
+ }
+
+ // If not, check to see if this node has a declared "FirstUnused" value that
+ // is less than the number of nodes allocated...
+ //
+ if (FirstUnused < SlabSize) {
+ // Successfully allocate out the first unused node
+ unsigned Idx = FirstUnused;
+ markNodeAllocated(Idx);
+ setStartBit(Idx);
+
+ // Increment FirstUnused to point to the new first unused value...
+ // FIXME: this should be optimized
+ unsigned short FU = FirstUnused;
+ do {
+ ++FU;
+ } while (FU != SlabSize && isNodeAllocated(FU));
+ FirstUnused = FU;
+
+ return Idx;
+ }
+
+ return -1;
+}
+
+// allocateMultiple - Allocate multiple contiguous elements from this pool,
+// returning -1 if there is no space.
+int PoolSlab::allocateMultiple(unsigned Size) {
+ // Do not allocate small arrays in SingleArray slabs
+ if (isSingleArray) return -1;
+
+ // For small array allocation, check to see if there are empty entries at the
+ // end of the slab...
+ if (UsedEnd+Size <= getSlabSize()) {
+ // Mark the returned entry used and set the start bit
+ unsigned UE = UsedEnd;
+ setStartBit(UE);
+ for (unsigned i = UE; i != UE+Size; ++i)
+ markNodeAllocated(i);
+
+ // If we are allocating out the first unused field, bump its index also
+ if (FirstUnused == UE)
+ FirstUnused += Size;
+
+ // Increment UsedEnd
+ UsedEnd += Size;
+
+ // Return the entry
+ return UE;
+ }
+
+ // If not, check to see if this node has a declared "FirstUnused" value
+ // starting which Size nodes can be allocated
+ //
+ unsigned Idx = FirstUnused;
+ while (Idx+Size <= getSlabSize()) {
+ assert(!isNodeAllocated(Idx) && "FirstUsed is not accurate!");
+
+ // Check if there is a continuous array of Size nodes starting FirstUnused
+ unsigned LastUnused = Idx+1;
+ for (; LastUnused != Idx+Size && !isNodeAllocated(LastUnused); ++LastUnused)
+ /*empty*/;
+
+ // If we found an unused section of this pool which is large enough, USE IT!
+ if (LastUnused == Idx+Size) {
+ setStartBit(Idx);
+ // FIXME: this loop can be made more efficient!
+ for (unsigned i = Idx; i != Idx + Size; ++i)
+ markNodeAllocated(i);
+
+ // This should not be allocating on the end of the pool, so we don't need
+ // to bump the UsedEnd pointer.
+ assert(Idx != UsedEnd && "Shouldn't allocate at end of pool!");
+
+ // If we are allocating out the first unused field, bump its index also.
+ if (Idx == FirstUnused)
+ FirstUnused += Size;
+
+ // Return the entry
+ return Idx;
+ }
+
+ // Otherwise, try later in the pool. Find the next unused entry.
+ Idx = LastUnused;
+ while (Idx+Size <= getSlabSize() && isNodeAllocated(Idx))
+ ++Idx;
+ }
+
+ return -1;
+}
+
+
+// containsElement - Return the element number of the specified address in
+// this slab. If the address is not in slab, return -1.
+int PoolSlab::containsElement(void *Ptr, unsigned ElementSize) const {
+ const void *FirstElement = getElementAddress(0, 0);
+ if (FirstElement <= Ptr) {
+ unsigned Delta = (char*)Ptr-(char*)FirstElement;
+ if (isSingleArray)
+ if (Delta < NumNodesInSlab) return Delta/ElementSize;
+ unsigned Index = Delta/ElementSize;
+ if (Index < getSlabSize()) {
+ if (Delta % ElementSize != 0) {
+ printf("Freeing pointer into the middle of an element!");
+ abort();
+ }
+
+ return Index;
+ }
+ }
+ return -1;
+}
+
+
+// freeElement - Free the single node, small array, or entire array indicated.
+void PoolSlab::freeElement(unsigned short ElementIdx) {
+ if (!isNodeAllocated(ElementIdx)) return;
+ // assert(isNodeAllocated(ElementIdx) &&
+ // "poolfree: Attempt to free node that is already freed\n");
+ assert(!isSingleArray && "Cannot free an element from a single array!");
+
+ // Mark this element as being free!
+ markNodeFree(ElementIdx);
+
+ // If this slab is not a SingleArray
+ assert(isStartOfAllocation(ElementIdx) &&
+ "poolfree: Attempt to free middle of allocated array\n");
+
+ // Free the first cell
+ clearStartBit(ElementIdx);
+ markNodeFree(ElementIdx);
+
+ // Free all nodes if this was a small array allocation.
+ unsigned short ElementEndIdx = ElementIdx + 1;
+
+ // FIXME: This should use manual strength reduction to produce decent code.
+ unsigned short UE = UsedEnd;
+ while (ElementEndIdx != UE &&
+ !isStartOfAllocation(ElementEndIdx) &&
+ isNodeAllocated(ElementEndIdx)) {
+ markNodeFree(ElementEndIdx);
+ ++ElementEndIdx;
+ }
+
+ // Update the first free field if this node is below the free node line
+ if (ElementIdx < FirstUnused) FirstUnused = ElementIdx;
+
+ // Update the first used field if this node was the first used.
+ if (ElementIdx == UsedBegin) UsedBegin = ElementEndIdx;
+
+ // If we are freeing the last element in a slab, shrink the UsedEnd marker
+ // down to the last used node.
+ if (ElementEndIdx == UE) {
+#if 0
+ printf("FU: %d, UB: %d, UE: %d FREED: [%d-%d)",
+ FirstUnused, UsedBegin, UsedEnd, ElementIdx, ElementEndIdx);
+#endif
+
+ // If the user is freeing the slab entirely in-order, it's quite possible
+ // that all nodes are free in the slab. If this is the case, simply reset
+ // our pointers.
+ if (UsedBegin == UE) {
+ //printf(": SLAB EMPTY\n");
+ FirstUnused = 0;
+ UsedBegin = 0;
+ UsedEnd = 0;
+ } else if (FirstUnused == ElementIdx) {
+ // Freed the last node(s) in this slab.
+ FirstUnused = ElementIdx;
+ UsedEnd = ElementIdx;
+ } else {
+ UsedEnd = lastNodeAllocated(ElementIdx);
+ assert(FirstUnused <= UsedEnd+1 &&
+ "FirstUnused field was out of date!");
+ }
+ }
+}
+
+unsigned PoolSlab::lastNodeAllocated(unsigned ScanIdx) {
+ // Check the last few nodes in the current word of flags...
+ unsigned CurWord = ScanIdx/16;
+ unsigned short Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+ if (Flags) {
+ // Mask off nodes above this one
+ Flags &= (1 << ((ScanIdx & 15)+1))-1;
+ if (Flags) {
+ // If there is still something in the flags vector, then there is a node
+ // allocated in this part. The goto is a hack to get the uncommonly
+ // executed code away from the common code path.
+ //printf("A: ");
+ goto ContainsAllocatedNode;
+ }
+ }
+
+ // Ok, the top word doesn't contain anything, scan the whole flag words now.
+ --CurWord;
+ while (CurWord != ~0U) {
+ Flags = NodeFlagsVector[CurWord] & 0xFFFF;
+ if (Flags) {
+ // There must be a node allocated in this word!
+ //printf("B: ");
+ goto ContainsAllocatedNode;
+ }
+ CurWord--;
+ }
+ return 0;
+
+ContainsAllocatedNode:
+ // Figure out exactly which node is allocated in this word now. The node
+ // allocated is the one with the highest bit set in 'Flags'.
+ //
+ // This should use __builtin_clz to get the value, but this builtin is only
+ // available with GCC 3.4 and above. :(
+ assert(Flags && "Should have allocated node!");
+
+ unsigned short MSB;
+#if GCC3_4_EVENTUALLY
+ MSB = 16 - ::__builtin_clz(Flags);
+#else
+ for (MSB = 15; (Flags & (1U << MSB)) == 0; --MSB)
+ /*empty*/;
+#endif
+
+ assert((1U << MSB) & Flags); // The bit should be set
+ assert((~(1U << MSB) & Flags) < Flags);// Removing it should make flag smaller
+ ScanIdx = CurWord*16 + MSB;
+ assert(isNodeAllocated(ScanIdx));
+ return ScanIdx;
+}
+
+
+//===----------------------------------------------------------------------===//
+//
+// Pool allocator library implementation
+//
+//===----------------------------------------------------------------------===//
+
+// poolinit - Initialize a pool descriptor to empty
+//
+void poolinit(PoolTy *Pool, unsigned NodeSize) {
+ assert(Pool && "Null pool pointer passed into poolinit!\n");
+ DEBUG(printf("pool init %x, %d\n", Pool, NodeSize);)
+
+ // Ensure the page manager is initialized
+ InitializePageManager();
+
+ // We must alway return unique pointers, even if they asked for 0 bytes
+ Pool->NodeSize = NodeSize ? NodeSize : 1;
+ Pool->Ptr1 = Pool->Ptr2 = 0;
+ Pool->LargeArrays = 0;
+ // For SAFECode, we set FreeablePool to 0 always
+ // Pool->FreeablePool = 0;
+ Pool->AllocadPool = -1;
+ Pool->lastUsed = 0;
+ Pool->prevPage[0] = 0;
+ Pool->prevPage[1] = 0;
+ // Initialize the SlabAddressArray to zero
+ for (int i = 0; i < AddrArrSize; ++i) {
+ Pool->SlabAddressArray[i] = 0;
+ }
+
+ Pool->NumSlabs = 0;
+
+ /// Pool->Slabs = new hash_set<void*>;
+ // Call hash_set constructor explicitly
+ // void *SlabPtr = &Pool->Slabs;
+ // new (SlabPtr) hash_set<void*>;
+}
+
+void poolmakeunfreeable(PoolTy *Pool) {
+ assert(Pool && "Null pool pointer passed in to poolmakeunfreeable!\n");
+ // Pool->FreeablePool = 0;
+}
+
+// pooldestroy - Release all memory allocated for a pool
+//
+void pooldestroy(PoolTy *Pool) {
+ assert(Pool && "Null pool pointer passed in to pooldestroy!\n");
+ if (Pool->AllocadPool) return;
+
+ if (Pool->NumSlabs > AddrArrSize) {
+ Pool->Slabs->clear();
+ delete Pool->Slabs;
+ }
+
+ // Free any partially allocated slabs
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+ while (PS) {
+ PoolSlab *Next = PS->Next;
+ PS->destroy();
+ PS = Next;
+ }
+
+ // Free the completely allocated slabs
+ PS = (PoolSlab*)Pool->Ptr2;
+ while (PS) {
+ PoolSlab *Next = PS->Next;
+ PS->destroy();
+ PS = Next;
+ }
+
+ // Free the large arrays
+ PS = (PoolSlab*)Pool->LargeArrays;
+ while (PS) {
+ PoolSlab *Next = PS->Next;
+ PS->destroy();
+ PS = Next;
+ }
+
+}
+
+
+// poolallocarray - a helper function used to implement poolalloc, when the
+// number of nodes to allocate is not 1.
+static void *poolallocarray(PoolTy* Pool, unsigned Size) {
+ assert(Pool && "Null pool pointer passed into poolallocarray!\n");
+ if (Size > PoolSlab::getSlabSize(Pool))
+ return PoolSlab::createSingleArray(Pool, Size);
+
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+
+ // Loop through all of the slabs looking for one with an opening
+ for (; PS; PS = PS->Next) {
+ int Element = PS->allocateMultiple(Size);
+ if (Element != -1) {
+ // We allocated an element. Check to see if this slab has been completely
+ // filled up. If so, move it to the Ptr2 list.
+ if (PS->isFull()) {
+ PS->unlinkFromList();
+ PS->addToList((PoolSlab**)&Pool->Ptr2);
+ }
+ return PS->getElementAddress(Element, Pool->NodeSize);
+ }
+ }
+
+ PoolSlab *New = PoolSlab::create(Pool);
+ // printf("new slab created %x \n", New);
+ if (Pool->NumSlabs > AddrArrSize)
+ Pool->Slabs->insert((void *)New);
+ else if (Pool->NumSlabs == AddrArrSize) {
+ // Create the hash_set
+ Pool->Slabs = new hash_set<void *>;
+ Pool->Slabs->insert((void *)New);
+ for (unsigned i = 0; i < AddrArrSize; ++i)
+ Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+ } else {
+ // Insert it in the array
+ Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) New;
+ }
+ Pool->NumSlabs++;
+
+ int Idx = New->allocateMultiple(Size);
+ assert(Idx == 0 && "New allocation didn't return zero'th node?");
+ return New->getElementAddress(0, 0);
+}
+
+void poolregister(PoolTy *Pool, unsigned NumBytes, void * allocaptr) {
+ if (!Pool) {
+ abort();
+ printf("Null pool pointer passed in to poolalloc!\n");
+ exit(-1);
+ }
+ if (Pool->AllocadPool != -1) {
+ if (Pool->AllocadPool == 0) {
+ printf(" Handle this case later\n");
+ exit(-1);
+ } else {
+ printf(" An allocad pool, you can only allocate once \n");
+ exit(-1);
+ }
+ } else {
+ Pool->AllocadPool = NumBytes;
+ Pool->allocaptr = allocaptr;
+ }
+}
+
+//Pool->AllocadPool -1 : unused so far
+//Pool->AllocadPool 0 : used only for mallocs
+//Pool->AllocadPool >0 : used for only allocas indicating the size
+void *poolalloc(PoolTy *Pool, unsigned NumBytes) {
+ void *retAddress = NULL;
+ if (!Pool) {
+ printf("Null pool pointer passed in to poolalloc!, FAILING\n");
+ exit(-1);
+ }
+ if (Pool->AllocadPool != -1) {
+ if (Pool->AllocadPool != 0) {
+ printf(" Did not Handle this case, an alloa and malloc point to");
+ printf("same DSNode, Will happen in stack safety \n");
+ exit(-1);
+ }
+ } else {
+ Pool->AllocadPool = 0;
+ }
+
+ unsigned NodeSize = Pool->NodeSize;
+ unsigned NodesToAllocate = (NumBytes+NodeSize-1)/NodeSize;
+ if (NodesToAllocate > 1) {
+ retAddress = poolallocarray(Pool, NodesToAllocate);
+ return retAddress;
+ }
+
+ // Special case the most common situation, where a single node is being
+ // allocated.
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+
+ if (__builtin_expect(PS != 0, 1)) {
+ int Element = PS->allocateSingle();
+ if (__builtin_expect(Element != -1, 1)) {
+ // We allocated an element. Check to see if this slab has been
+ // completely filled up. If so, move it to the Ptr2 list.
+ if (__builtin_expect(PS->isFull(), false)) {
+ PS->unlinkFromList();
+ PS->addToList((PoolSlab**)&Pool->Ptr2);
+ }
+ retAddress = PS->getElementAddress(Element, NodeSize);
+ // printf(" returning the address %x",retAddress);
+ return retAddress;
+ }
+
+ // Loop through all of the slabs looking for one with an opening
+ for (PS = PS->Next; PS; PS = PS->Next) {
+ int Element = PS->allocateSingle();
+ if (Element != -1) {
+ // We allocated an element. Check to see if this slab has been
+ // completely filled up. If so, move it to the Ptr2 list.
+ if (PS->isFull()) {
+ PS->unlinkFromList();
+ PS->addToList((PoolSlab**)&Pool->Ptr2);
+ }
+
+ retAddress = PS->getElementAddress(Element, NodeSize);
+ //printf(" returning the address %x",retAddress);
+ return retAddress;
+ }
+ }
+ }
+
+ // Otherwise we must allocate a new slab and add it to the list
+ PoolSlab *New = PoolSlab::create(Pool);
+
+ if (Pool->NumSlabs > AddrArrSize)
+ Pool->Slabs->insert((void *)New);
+ else if (Pool->NumSlabs == AddrArrSize) {
+ // Create the hash_set
+ Pool->Slabs = new hash_set<void *>;
+ Pool->Slabs->insert((void *)New);
+ for (unsigned i = 0; i < AddrArrSize; ++i)
+ Pool->Slabs->insert((void *)Pool->SlabAddressArray[i]);
+ } else {
+ // Insert it in the array
+ Pool->SlabAddressArray[Pool->NumSlabs] = (unsigned) New;
+ }
+ Pool->NumSlabs++;
+
+ int Idx = New->allocateSingle();
+ assert(Idx == 0 && "New allocation didn't return zero'th node?");
+ retAddress = New->getElementAddress(0, 0);
+ // printf(" returning the address %x",retAddress);
+ return retAddress;
+}
+
+/*
+// SearchForContainingSlab - This implementation uses the hash_set as well
+// as the array to search the list of allocated slabs for the node in question
+static PoolSlab *SearchForContainingSlab(PoolTy *Pool, void *Node,
+ unsigned &TheIndex) {
+ // printf("in pool check for pool %x, node %x\n",Pool,Node);
+ unsigned NodeSize = Pool->NodeSize;
+ void *PS;
+ if (!Pool) {
+ printf("Empty Pool in pool check FAILING \n");
+ exit(-1);
+ }
+ assert (Pool->AllocadPool <= 0 && "SearchForContainingSlab not to be called"
+ " for alloca'ed pools");
+
+ PS = (void*)((long)Node & ~(PageSize-1));
+ if (Pool->NumSlabs > AddrArrSize) {
+ hash_set<void*> &theSlabs = *Pool->Slabs;
+ if (theSlabs.find(PS) == theSlabs.end()) {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ unsigned Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PSlab = PSlab->Next;
+ }
+ if (Idx == -1) {
+ printf("poolcheck: node being checked not found in pool \n");
+ abort();
+ }
+ TheIndex = Idx;
+ return PSlab;
+ } else {
+ printf("poolcheck: node being checked not found in pool \n");
+ abort();
+ }
+ } else {
+ // Check that Node does not point to PoolSlab meta-data
+ if ((PoolSlab *)PS->getElementAddress(0,0) > (long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ abort();
+ }
+ TheIndex = PS->containsElement(Node, NodeSize);
+ return (PoolSlab *)PS;
+ }
+ } else {
+ bool found;
+ for (unsigned i = 0; i < AddrArrSize && !found; ++i) {
+ if (Pool->SlabAddressArray[i] == (unsigned) PS)
+ found = true;
+ }
+
+ if (found) {
+ // Check that Node does not point to PoolSlab meta-data
+ if ((PoolSlab *)PS->getElementAddress(0,0) > (long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ abort();
+ }
+ TheIndex = PS->containsElement(Node, NodeSize);
+ return (PoolSlab *)PS;
+ } else {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ unsigned Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PSlab = PSlab->Next;
+ }
+ if (Idx == -1) {
+ printf("poolcheck: node being checked not found in pool \n");
+ abort();
+ }
+ TheIndex = Idx;
+ return PSlab;
+ }
+ printf("poolcheck: node being checked not found in pool \n");
+ abort();
+ }
+ }
+}
+*/
+
+// SearchForContainingSlab - Do a brute force search through the list of
+// allocated slabs for the node in question.
+//
+static PoolSlab *SearchForContainingSlab(PoolTy *Pool, void *Node,
+ unsigned &TheIndex) {
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+ unsigned NodeSize = Pool->NodeSize;
+
+ // Search the partially allocated slab list for the slab that contains this
+ // node.
+ int Idx = -1;
+ if (PS) { // Pool->Ptr1 could be null if Ptr2 isn't
+ for (; PS; PS = PS->Next) {
+ Idx = PS->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ }
+ }
+
+ // If the partially allocated slab list doesn't contain it, maybe the
+ // completely allocated list does.
+ if (PS == 0) {
+ PS = (PoolSlab*)Pool->Ptr2;
+ assert(Idx == -1 && "Found node but don't have PS?");
+
+ while (PS) {
+ assert(PS && "poolfree: node being free'd not found in allocation "
+ " pool specified!\n");
+ Idx = PS->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PS = PS->Next;
+ }
+ }
+
+ // Otherwise, maybe its a block within LargeArrays
+ if(PS == 0) {
+ PS = (PoolSlab*)Pool->LargeArrays;
+ assert(Idx == -1 && "Found node but don't have PS?");
+
+ while (PS) {
+ assert(PS && "poolfree: node being free'd not found in allocation "
+ " pool specified!\n");
+ Idx = PS->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PS = PS->Next;
+ }
+ }
+
+ TheIndex = Idx;
+ return PS;
+}
+
+void poolcheckoptim(PoolTy *Pool, void *Node) {
+ if (Pool->AllocadPool > 0) {
+ if (Pool->allocaptr <= Node) {
+ unsigned diffPtr = (unsigned)Node - (unsigned)Pool->allocaptr;
+ unsigned offset = diffPtr % Pool->NodeSize;
+ if ((diffPtr < Pool->AllocadPool ) && (offset >= 0))
+ return;
+ }
+ PCheckPassed = 0;
+ abort();
+ }
+
+ PoolSlab *PS = (PoolSlab*)((long)Node & ~(PageSize-1));
+
+ if (Pool->NumSlabs > AddrArrSize) {
+ hash_set<void*> &theSlabs = *Pool->Slabs;
+ if (theSlabs.find((void*)PS) == theSlabs.end()) {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ int Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ if (Idx != -1) {
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ break;
+ }
+ PSlab = PSlab->Next;
+ }
+
+ if (Idx == -1) {
+ printf ("poolcheck1: node being checked not found in pool with right"
+ " alignment\n");
+ PCheckPassed = 0;
+ abort();
+ exit(-1);
+ } else {
+ //exit(-1);
+ }
+ } else {
+ printf ("poolcheck2: node being checked not found in pool with right"
+ " alignment\n");
+ abort();
+ exit(-1);
+ }
+ } else {
+ unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+ if (startaddr > (unsigned long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ abort();
+ }
+ unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+ if (offset != 0) {
+ printf ("poolcheck3: node being checked does not have right alignment\n");
+ abort();
+ }
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ }
+ } else {
+ bool found = false;
+ for (unsigned i = 0; i < AddrArrSize && !found; ++i) {
+ if ((unsigned)Pool->SlabAddressArray[i] == (unsigned) PS) {
+ found = true;
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ }
+ }
+
+ if (found) {
+ // Check that Node does not point to PoolSlab meta-data
+ unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+ if (startaddr > (unsigned long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ exit(-1);
+ }
+ unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+ if (offset != 0) {
+ printf("poolcheck4: node being checked does not have right alignment\n");
+ abort();
+ }
+ } else {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ int Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ if (Idx != -1) {
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ break;
+ }
+ PSlab = PSlab->Next;
+ }
+ if (Idx == -1) {
+ printf ("poolcheck6: node being checked not found in pool with right"
+ " alignment\n");
+ abort();
+ }
+ } else {
+ printf ("poolcheck5: node being checked not found in pool with right"
+ " alignment %x %x\n",Pool,Node);
+ abort();
+ }
+ }
+ }
+}
+
+void poolcheck(PoolTy *Pool, void *Node) {
+ PoolSlab *PS;
+ PS = (PoolSlab*)((long)Node & ~(PageSize-1));
+ if (Pool->prevPage[0] == PS) {
+ return;
+ }
+ if (Pool->prevPage[1] == PS) {
+ return;
+ }
+ if (Pool->prevPage[2] == PS) {
+ return;
+ }
+ if (Pool->prevPage[3] == PS) {
+ return;
+ }
+ poolcheckoptim(Pool, Node);
+}
+
+
+
+// Check that Node falls within the pool and within start and (including)
+// end offset
+void poolcheckalign (PoolTy *Pool, void *Node, unsigned StartOffset,
+ unsigned EndOffset) {
+ PoolSlab *PS;
+ if (StartOffset >= Pool->NodeSize || EndOffset >= Pool->NodeSize) {
+ printf("Error: Offset specified exceeded node size");
+ exit(-1);
+ }
+
+ if (Pool->AllocadPool > 0) {
+ if (Pool->allocaptr <= Node) {
+ unsigned diffPtr = (unsigned)Node - (unsigned)Pool->allocaptr;
+ unsigned offset = diffPtr % Pool->NodeSize;
+ if ((diffPtr < Pool->AllocadPool ) && (offset >= StartOffset) &&
+ (offset <= EndOffset))
+ return;
+ }
+ assert(0 && "poolcheckalign failure FAILING \n");
+ exit(-1);
+ }
+
+ PS = (PoolSlab*)((long)Node & ~(PageSize-1));
+
+ if (Pool->NumSlabs > AddrArrSize) {
+ hash_set<void*> &theSlabs = *Pool->Slabs;
+ if (theSlabs.find((void*)PS) == theSlabs.end()) {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ int Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ if (Idx != -1) {
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ break;
+ }
+ PSlab = PSlab->Next;
+ }
+
+ if (Idx == -1) {
+ printf("poolcheck1: node being checked not found in pool with right"
+ " alignment\n");
+ abort();
+ exit(-1);
+ } else {
+ //exit(-1);
+ }
+ } else {
+ printf("poolcheck2: node being checked not found in pool with right"
+ " alignment\n");
+ abort();
+ exit(-1);
+ }
+ } else {
+ unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+ if (startaddr > (unsigned long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ abort();
+ exit(-1);
+ }
+ unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+ if ((offset < StartOffset) || (offset > EndOffset)) {
+ printf("poolcheck3: node being checked does not have right alignment\n");
+ abort();
+ exit(-1);
+ }
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ }
+ } else {
+ bool found = false;
+ for (unsigned i = 0; i < AddrArrSize && !found; ++i) {
+ if ((unsigned)Pool->SlabAddressArray[i] == (unsigned) PS) {
+ found = true;
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ }
+ }
+
+ if (found) {
+ // Check that Node does not point to PoolSlab meta-data
+ unsigned long startaddr = (unsigned long)PS->getElementAddress(0,0);
+ if (startaddr > (unsigned long) Node) {
+ printf("poolcheck: node being checked points to meta-data \n");
+ exit(-1);
+ }
+ unsigned long offset = ((unsigned long) Node - (unsigned long) startaddr) % Pool->NodeSize;
+ if ((offset < StartOffset) || (offset > EndOffset)) {
+ printf("poolcheck4: node being checked does not have right alignment\n");
+ abort();
+ exit(-1);
+ }
+ } else {
+ // Check the LargeArrays
+ if (Pool->LargeArrays) {
+ PoolSlab *PSlab = (PoolSlab*) Pool->LargeArrays;
+ int Idx = -1;
+ while (PSlab) {
+ assert(PSlab && "poolcheck: node being free'd not found in "
+ "allocation pool specified!\n");
+ Idx = PSlab->containsElement(Node, Pool->NodeSize);
+ if (Idx != -1) {
+ Pool->prevPage[Pool->lastUsed] = PS;
+ Pool->lastUsed = (Pool->lastUsed + 1) % 4;
+ break;
+ }
+ PSlab = PSlab->Next;
+ }
+ if (Idx == -1) {
+ printf("poolcheck6: node being checked not found in pool with right"
+ " alignment\n");
+ abort();
+ exit(-1);
+ }
+ } else {
+ printf("poolcheck5: node being checked not found in pool with right"
+ " alignment %x %x\n",Pool,Node);
+ abort();
+ }
+ }
+ }
+}
+
+
+/*
+void poolcheck(PoolTy *Pool, void *Node) {
+ PoolSlab *PS = (PoolSlab*)Pool->Ptr1;
+ unsigned NodeSize = Pool->NodeSize;
+
+ // Search the partially allocated slab list for the slab that contains this
+ // node.
+ int Idx = -1;
+ if (PS) { // Pool->Ptr1 could be null if Ptr2 isn't
+ for (; PS; PS = PS->Next) {
+ Idx = PS->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ }
+ }
+
+ // If the partially allocated slab list doesn't contain it, maybe the
+ // completely allocated list does.
+ if (PS == 0) {
+ PS = (PoolSlab*)Pool->Ptr2;
+ while (1) {
+ assert(PS && "poolcheck: node being checked not found in pool "
+ " specified!\n");
+ Idx = PS->containsElement(Node, NodeSize);
+ if (Idx != -1) break;
+ PS = PS->Next;
+ }
+ }
+}
+*/
+
+void poolfree(PoolTy *Pool, void *Node) {
+ assert(Pool && "Null pool pointer passed in to poolfree!\n");
+ DEBUG(printf("poolfree %x %x \n",Pool,Node);)
+ PoolSlab *PS;
+ int Idx;
+ if (1) { // THIS SHOULD BE SET FOR SAFECODE!
+ unsigned TheIndex;
+ PS = SearchForContainingSlab(Pool, Node, TheIndex);
+ Idx = TheIndex;
+ } else {
+ // Since it is undefined behavior to free a node which has not been
+ // allocated, we know that the pointer coming in has to be a valid node
+ // pointer in the pool. Mask off some bits of the address to find the base
+ // of the pool.
+ assert((PageSize & PageSize-1) == 0 && "Page size is not a power of 2??");
+ PS = (PoolSlab*)((long)Node & ~(PageSize-1));
+
+ if (PS->isSingleArray) {
+ PS->unlinkFromList();
+ PS->destroy();
+ return;
+ }
+
+ Idx = PS->containsElement(Node, Pool->NodeSize);
+ assert((int)Idx != -1 && "Node not contained in slab??");
+ }
+
+ // If PS was full, it must have been in list #2. Unlink it and move it to
+ // list #1.
+ if (PS->isFull()) {
+ // Now that we found the node, we are about to free an element from it.
+ // This will make the slab no longer completely full, so we must move it to
+ // the other list!
+ PS->unlinkFromList(); // Remove it from the Ptr2 list.
+
+ PoolSlab **InsertPosPtr = (PoolSlab**)&Pool->Ptr1;
+
+ // If the partially full list has an empty node sitting at the front of the
+ // list, insert right after it.
+ if ((*InsertPosPtr)->isEmpty())
+ InsertPosPtr = &(*InsertPosPtr)->Next;
+
+ PS->addToList(InsertPosPtr); // Insert it now in the Ptr1 list.
+ }
+
+ // Free the actual element now!
+ PS->freeElement(Idx);
+
+ // Ok, if this slab is empty, we unlink it from the of slabs and either move
+ // it to the head of the list, or free it, depending on whether or not there
+ // is already an empty slab at the head of the list.
+ //
+ if (PS->isEmpty()) {
+ PS->unlinkFromList(); // Unlink from the list of slabs...
+
+ // If we can free this pool, check to see if there are any empty slabs at
+ // the start of this list. If so, delete the FirstSlab!
+ PoolSlab *FirstSlab = (PoolSlab*)Pool->Ptr1;
+ if (0 && FirstSlab && FirstSlab->isEmpty()) {
+ // Here we choose to delete FirstSlab instead of the pool we just freed
+ // from because the pool we just freed from is more likely to be in the
+ // processor cache.
+ FirstSlab->unlinkFromList();
+ FirstSlab->destroy();
+ // Pool->Slabs.erase((void *)FirstSlab);
+ }
+
+ // Link our slab onto the head of the list so that allocations will find it
+ // efficiently.
+ PS->addToList((PoolSlab**)&Pool->Ptr1);
+ }
+}
diff --git a/safecode/test/Makefile b/safecode/test/Makefile
new file mode 100755
index 0000000..5a7c9f7
--- /dev/null
+++ b/safecode/test/Makefile
@@ -0,0 +1,231 @@
+##===- safecode/test/Makefile ------------------------------*- Makefile -*-===##
+#
+# Define the default test rule, which allows people to just type 'make test' in
+# this directory.
+#
+##===----------------------------------------------------------------------===##
+
+# The default target in this directory is the test:: target
+test::
+
+LEVEL = ..
+include $(LEVEL)/Makefile.common
+
+ifndef NO_STABLE_NUMBERS
+STABLERUN := GET_STABLE_NUMBERS=1
+else
+STABLERUN :=
+endif
+
+ifndef NO_LARGE_SIZE
+LARGESIZE := LARGE_PROBLEM_SIZE=1
+else
+LARGESIZE :=
+endif
+
+
+LARGE_PROBLEM_SIZE_DIRS :=
+
+
+LARGE_PROBLEM_SIZE_DIRS := \
+ $(addprefix $(LLVM_OBJ_ROOT)/projects/llvm-test/,$(LARGE_PROBLEM_SIZE_DIRS))
+
+
+NORMAL_PROBLEM_SIZE_DIRS := \
+ MultiSource/Benchmarks/Olden
+ #MultiSource/Benchmarks/Ptrdist
+ #MultiSource/Applications \
+ #MultiSource/Benchmarks
+
+
+NORMAL_PROBLEM_SIZE_DIRS := \
+ $(addprefix $(LLVM_OBJ_ROOT)/projects/llvm-test/,$(NORMAL_PROBLEM_SIZE_DIRS))
+
+##############################################################################
+# Targets for gathering statistics for programs for papers
+##############################################################################
+
+# Program tests for Pool Allocation
+progtest::
+ for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=safecode \
+ POOLALLOC_OBJDIR=$(POOLALLOC_OBJDIR) LARGE_PROBLEM_SIZE=1 report.html) \
+ done
+ for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=safecode \
+ report.html) \
+ done
+ @for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=safecode \
+ LARGE_PROBLEM_SIZE=1 report) \
+ done
+ @for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=safecode \
+ report) \
+ done
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+progabc::
+ for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=abc \
+ POOLALLOC_OBJDIR=$(POOLALLOC_OBJDIR) LARGE_PROBLEM_SIZE=1 report.html) \
+ done
+ for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=abc \
+ report.html) \
+ done
+ @for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=abc \
+ LARGE_PROBLEM_SIZE=1 report) \
+ done
+ @for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=abc \
+ report) \
+ done
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+
+progperf::
+ for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=perf \
+ LARGE_PROBLEM_SIZE=1 report.html report.csv) \
+ done
+ for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=perf \
+ report.html report.csv) \
+ done
+ @for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=perf \
+ LARGE_PROBLEM_SIZE=1 report report.csv) \
+ done
+ @for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=perf \
+ report report.csv) \
+ done
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+progp4perf::
+ for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=p4perf \
+ LARGE_PROBLEM_SIZE=1 report.html report.csv) \
+ done
+ for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=p4perf \
+ report.html report.csv) \
+ done
+ @for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=p4perf \
+ LARGE_PROBLEM_SIZE=1 report report.csv) \
+ done
+ @for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=p4perf \
+ report report.csv) \
+ done
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+progcputrack::
+ for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=cputrack \
+ LARGE_PROBLEM_SIZE=1 report.html report.csv) \
+ done
+ for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=cputrack \
+ report.html report.csv) \
+ done
+ @for dir in $(LARGE_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=cputrack \
+ LARGE_PROBLEM_SIZE=1 report report.csv) \
+ done
+ @for dir in $(NORMAL_PROBLEM_SIZE_DIRS); do \
+ (cd $$dir; \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -s -j1 TEST=cputrack \
+ report report.csv) \
+ done
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+
+##############################################################################
+# Targets for running tests and gathering statistics for arbitrary tests
+##############################################################################
+
+# test target - Descend into projects/llvm-test and run the TEST.safecode.Makefile
+# tests...
+test::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=safecode \
+ $(LARGESIZE) $(STABLERUN) report report.html)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+pacompiletime::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=pacompiletime \
+ report report.html)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+ptrcomp::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=ptrcomp \
+ $(LARGESIZE) $(STABLERUN) report report.html)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+ptrcomptest::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=ptrcomp \
+ $(LARGESIZE) report)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+vtl::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=pavtl \
+ test report report.csv)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+perf::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=perf \
+ test report report.csv)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+optzn::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=optzn \
+ $(LARGESIZE) $(STABLERUN) test report report.csv)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+p4perf::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=p4perf \
+ test report report.csv)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+strace::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=strace \
+ test)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
+cputrack::
+ (cd $(LLVM_OBJ_ROOT)/projects/llvm-test/$(SUBDIR); \
+ PROJECT_DIR=$(PROJ_OBJ_ROOT) $(MAKE) -j1 TEST=cputrack \
+ report report.csv)
+ @printf "\a"; sleep 1; printf "\a"; sleep 1; printf "\a"
+
diff --git a/safecode/test/TEST.abc.Makefile b/safecode/test/TEST.abc.Makefile
new file mode 100755
index 0000000..31bb940
--- /dev/null
+++ b/safecode/test/TEST.abc.Makefile
@@ -0,0 +1,178 @@
+##===- safecode/test/TEST.abc.Makefile ---------------------*- Makefile -*-===##
+#
+# This test runs SAFECode on all of the Programs, producing some
+# performance numbers and statistics.
+#
+##===----------------------------------------------------------------------===##
+
+include $(PROJ_OBJ_ROOT)/Makefile.common
+
+CFLAGS = -O3 -fno-strict-aliasing
+ABCFLAGS = -include /home/vadve/criswell/Downloads/SAFECode/lib/poolcheck.c -I/home/vadve/criswell/Downloads/SAFECode/include
+
+CURDIR := $(shell cd .; pwd)
+PROGDIR := $(shell cd $(LLVM_SRC_ROOT)/projects/llvm-test; pwd)/
+RELDIR := $(subst $(PROGDIR),,$(CURDIR))
+GCCLD = $(LLVM_OBJ_ROOT)/$(CONFIGURATION)/bin/gccld
+
+# Pool allocator pass shared object
+PA_SO := /home/vadve/criswell/Downloads/SAFECode/bin/boundschecker
+
+# Pool allocator runtime library
+#PA_RT := $(PROJECT_DIR)/lib/Bytecode/libpoolalloc_fl_rt.bc
+#PA_RT_O := $(PROJECT_DIR)/$(CONFIGURATION)/lib/libpoolalloc_splay_rt.bca
+#PA_RT_O := $(PROJECT_DIR)/$(CONFIGURATION)/lib/poolalloc_splay_rt.o
+#PA_RT_O := $(PROJECT_DIR)/$(CONFIGURATION)/lib/poolalloc_safe_rt.o
+#PA_RT_O := $(PROJECT_DIR)/Release/lib/poolalloc_rt.o
+#PA_RT_O := $(PROJECT_DIR)/lib/Release/poolalloc_fl_rt.o
+PA_RT_O := /home/vadve/criswell/Downloads/SAFECode/lib/libpoolalloc_splay_rt.a
+
+# Command to run opt with the pool allocator pass loaded
+OPT_SC := /home/vadve/criswell/Downloads/SAFECode/bin/boundschecker \
+ -poolalloc-disable-alignopt \
+ -poolalloc-usetd-resolve \
+ -budatastructures-update-from-globals \
+ -poolalloc-force-simple-pool-init \
+ -poolalloc-force-all-poolfrees \
+ -poolalloc-add-pooldescs-globalstack-arrays \
+ -poolalloc-add-pooldescs-collapsed \
+ -poolalloc-heuristic=AllNodes \
+ -poolalloc-keep-DSA-results
+
+#OPT_SC := /home/vadve/criswell/Downloads/SAFECode/bin/boundschecker \
+ #-poolalloc-force-simple-pool-init \
+ #-poolalloc-force-all-poolfrees \
+ #-poolalloc-add-pooldescs-globalstack-arrays \
+ #-poolalloc-heuristic=AllNodes \
+ #-poolalloc-keep-DSA-results
+
+# OPT_SC_STATS - Run opt with the -stats and -time-passes options, capturing the
+# output to a file.
+OPT_SC_STATS = $(OPT_SC) -info-output-file=$(CURDIR)/$@.info -stats -time-passes
+
+#OPTZN_PASSES := -globaldce -ipsccp -deadargelim -adce -instcombine -simplifycfg
+OPTZN_PASSES :=
+
+
+#
+# This rule runs SAFECode on the .llvm.bc file to produce a new .bc
+# file
+#
+$(PROGRAMS_TO_TEST:%=Output/%.$(TEST).bc): \
+Output/%.$(TEST).bc: Output/%.llvm.bc $(PA_SO) $(LOPT)
+ -@rm -f $(CURDIR)/$@.info
+ -$(OPT_SC_STATS) $(OPTZN_PASSES) $< -o $@ -f 2>&1 > $@.out
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.bc): \
+Output/%.nonsc.bc: Output/%.llvm.bc $(LOPT)
+ -@rm -f $(CURDIR)/$@.info
+ -$(LOPT) $(OPTZN_PASSES) $< -o $@ -f 2>&1 > $@.out
+
+#
+# These rules compile the new .bc file into a .c file using CBE
+#
+$(PROGRAMS_TO_TEST:%=Output/%.abc.cbe.c): \
+Output/%.abc.cbe.c: Output/%.$(TEST).bc $(LLC)
+ -$(LLC) -march=c -f $< -o $@
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.cbe.c): \
+Output/%.nonsc.cbe.c: Output/%.nonsc.bc $(LLC)
+ -$(LLC) -march=c -f $< -o $@
+
+#
+# These rules compile the CBE .c file into a final executable
+#
+$(PROGRAMS_TO_TEST:%=Output/%.abc.cbe): \
+Output/%.abc.cbe: Output/%.abc.cbe.c $(PA_RT_O)
+ -$(CC) $(CFLAGS) $(ABCFLAGS) $< $(LLCLIBS) $(LDFLAGS) $(PA_RT_O) -o $@
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.cbe): \
+Output/%.nonsc.cbe: Output/%.nonsc.cbe.c $(PA_RT_O)
+ -$(CC) $(CFLAGS) $< $(LLCLIBS) $(LDFLAGS) -o $@
+
+
+
+ifndef PROGRAMS_HAVE_CUSTOM_RUN_RULES
+
+#
+# This rule runs the generated executable, generating timing information, for
+# normal test programs
+#
+$(PROGRAMS_TO_TEST:%=Output/%.abc.out-cbe): \
+Output/%.abc.out-cbe: Output/%.abc.cbe
+ -$(RUNSAFELY) $(STDIN_FILENAME) $@ $< $(RUN_OPTIONS)
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.out-cbe): \
+Output/%.nonsc.out-cbe: Output/%.nonsc.cbe
+ -$(RUNSAFELY) $(STDIN_FILENAME) $@ $< $(RUN_OPTIONS)
+
+else
+
+#
+# This rule runs the generated executable, generating timing information, for
+# SPEC
+#
+$(PROGRAMS_TO_TEST:%=Output/%.abc.out-cbe): \
+Output/%.abc.out-cbe: Output/%.abc.cbe
+ -$(SPEC_SANDBOX) abccbe-$(RUN_TYPE) $@ $(REF_IN_DIR) \
+ $(RUNSAFELY) $(STDIN_FILENAME) $(STDOUT_FILENAME) \
+ ../../$< $(RUN_OPTIONS)
+ -(cd Output/abccbe-$(RUN_TYPE); cat $(LOCAL_OUTPUTS)) > $@
+ -cp Output/abccbe-$(RUN_TYPE)/$(STDOUT_FILENAME).time $@.time
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.out-cbe): \
+Output/%.nonsc.out-cbe: Output/%.nonsc.cbe
+ -$(SPEC_SANDBOX) nonsccbe-$(RUN_TYPE) $@ $(REF_IN_DIR) \
+ $(RUNSAFELY) $(STDIN_FILENAME) $(STDOUT_FILENAME) \
+ ../../$< $(RUN_OPTIONS)
+ -(cd Output/nonsccbe-$(RUN_TYPE); cat $(LOCAL_OUTPUTS)) > $@
+ -cp Output/nonsccbe-$(RUN_TYPE)/$(STDOUT_FILENAME).time $@.time
+
+endif
+
+
+# This rule diffs the post-poolallocated version to make sure we didn't break
+# the program!
+$(PROGRAMS_TO_TEST:%=Output/%.abc.diff-cbe): \
+Output/%.abc.diff-cbe: Output/%.out-nat Output/%.abc.out-cbe
+ @cp Output/$*.out-nat Output/$*.abc.out-nat
+ -$(DIFFPROG) cbe $*.abc $(HIDEDIFF)
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.diff-cbe): \
+Output/%.nonsc.diff-cbe: Output/%.out-nat Output/%.nonsc.out-cbe
+ @cp Output/$*.out-nat Output/$*.nonsc.out-nat
+ -$(DIFFPROG) cbe $*.nonsc $(HIDEDIFF)
+
+
+# This rule wraps everything together to build the actual output the report is
+# generated from.
+$(PROGRAMS_TO_TEST:%=Output/%.$(TEST).report.txt): \
+Output/%.$(TEST).report.txt: Output/%.out-nat \
+ Output/%.nonsc.diff-cbe \
+ Output/%.abc.diff-cbe \
+ Output/%.LOC.txt
+ @echo > $@
+ @-if test -f Output/$*.nonsc.diff-cbe; then \
+ printf "GCC-RUN-TIME: " >> $@;\
+ grep "^program" Output/$*.out-nat.time >> $@;\
+ fi
+ @-if test -f Output/$*.nonsc.diff-cbe; then \
+ printf "CBE-RUN-TIME-NORMAL: " >> $@;\
+ grep "^program" Output/$*.nonsc.out-cbe.time >> $@;\
+ fi
+ @-if test -f Output/$*.abc.diff-cbe; then \
+ printf "CBE-RUN-TIME-SAFECODE: " >> $@;\
+ grep "^program" Output/$*.abc.out-cbe.time >> $@;\
+ fi
+ printf "LOC: " >> $@
+ cat Output/$*.LOC.txt >> $@
+ @cat Output/$*.$(TEST).bc.info >> $@
+
+$(PROGRAMS_TO_TEST:%=test.$(TEST).%): \
+test.$(TEST).%: Output/%.$(TEST).report.txt
+ @echo "---------------------------------------------------------------"
+ @echo ">>> ========= '$(RELDIR)/$*' Program"
+ @echo "---------------------------------------------------------------"
+ @cat $<
+
+REPORT_DEPENDENCIES := $(PA_RT_O) $(PA_SO) $(PROGRAMS_TO_TEST:%=Output/%.llvm.bc) $(LLC) $(LOPT)
diff --git a/safecode/test/TEST.abc.report b/safecode/test/TEST.abc.report
new file mode 100755
index 0000000..d24597e
--- /dev/null
+++ b/safecode/test/TEST.abc.report
@@ -0,0 +1,95 @@
+##=== TEST.poolalloc.report - Report description for poolalloc -*- perl -*-===##
+#
+# This file defines a report to be generated for the pool allocator tests.
+#
+##===----------------------------------------------------------------------===##
+
+# Sort by program name
+$SortCol = 0;
+$TrimRepeatedPrefix = 1;
+
+# FormatTime - Convert a time from 1m23.45 into 83.45
+sub FormatTime {
+ my $Time = shift;
+ if ($Time =~ m/([0-9]+)[m:]([0-9.]+)/) {
+ return sprintf("%7.3f", $1*60.0+$2);
+ }
+
+ return sprintf("%6.2f", $Time);
+}
+
+
+sub RuntimePercent {
+ my ($Cols, $Col) = @_;
+ if ($Cols->[$Col-1] ne "*" and $Cols->[4] ne "*" and
+ $Cols->[4] != "0") {
+ return sprintf "%7.2f", 100*$Cols->[$Col-1]/$Cols->[4];
+ } else {
+ return "n/a";
+ }
+}
+
+@LatexColumns = (1, 5, 8, 12, 9, 13, 14, 15, 2, 16);
+
+my $FREEBENCH = 'MultiSource/Benchmarks/FreeBench';
+my $PTRDIST = 'MultiSource/Benchmarks/Ptrdist';
+
+@LatexRowMapOrder = (
+ '164.gzip/164.gzip' => '164.gzip',
+ '175.vpr/175.vpr' => '175.vpr',
+ '181.mcf/181.mcf' => '181.mcf',
+ '186.crafty/186.crafty' => '186.crafty',
+ '197.parser/197.parser' => '197.parser',
+ '197.parser.hacked/197.parser.hacked' => '197.parser(b)',
+ '255.vortex/255.vortex' => '255.vortex',
+ '256.bzip2/256.bzip2' => '256.bzip2',
+ '300.twolf/300.twolf' => '300.twolf',
+ '-' => '-',
+ "anagram/anagram" => 'anagram',
+ "bc/bc" => 'bc',
+ "ft/ft" => 'ft',
+ "ks/ks" => 'ks',
+ "yacr2/yacr2" => 'yacr2',
+ '-' => '-',
+ "analyzer" => 'analyzer',
+ "neural" => 'neural',
+ "pcompress2" => 'pcompress2',
+ "piff2" => 'piff2',
+ '-' => '-',
+ "bh/bh" => 'bh',
+ "bisort/bisort" => 'bisort',
+ "em3d/em3d" => 'em3d',
+ "health/health" => 'health',
+ "mst/mst" => 'mst',
+ "perimeter/perimeter" => 'perimeter',
+ "power/power" => 'power',
+ "treeadd/treeadd" => 'treeadd',
+ "tsp/tsp" => 'tsp',
+ '-' => '-',
+ "llu" => 'llu-bench',
+ );
+
+
+# These are the columns for the report. The first entry is the header for the
+# column, the second is the regex to use to match the value. Empty list create
+# seperators, and closures may be put in for custom processing.
+(
+# Name
+ ["Name:" , '\'([^\']+)\' Program'],
+ ["LOC" , 'LOC:\s*([0-9]+)'],
+ [],
+# Times
+ ["GCC", 'GCC-RUN-TIME: program\s*([.0-9m:]+)', \&FormatTime],
+ ["NonPATime", 'CBE-RUN-TIME-NORMAL: program\s*([.0-9m:]+)', \&FormatTime],
+ [],
+ ["SC Time", 'CBE-RUN-TIME-SAFECODE: program\s*([.0-9m:]+)', \&FormatTime],
+# ["NumPools", '([0-9]+).*Number of pools allocated'],
+# ["Typesafe", '([0-9]+).*Number of typesafe pools'],
+# ["BumpPtr", '([0-9]+).*Number of bump pointer pools'],
+# ["PFE", '([0-9]+).*Number of poolfree.s elided'],
+# ["NumArgs", '([0-9]+).*Number of function arguments added'],
+# ["MaxArgs", '([0-9]+).*Maximum function arguments added'],
+#["Nonprofit", '([0-9]+).*Number of DSNodes not profitable'],
+ []
+);
+
diff --git a/safecode/test/TEST.safecode.Makefile b/safecode/test/TEST.safecode.Makefile
new file mode 100755
index 0000000..8d16b10
--- /dev/null
+++ b/safecode/test/TEST.safecode.Makefile
@@ -0,0 +1,168 @@
+##===- safecode/test/TEST.safecode.Makefile ----------------*- Makefile -*-===##
+#
+# This test runs SAFECode on all of the Programs, producing some
+# performance numbers and statistics.
+#
+##===----------------------------------------------------------------------===##
+
+include $(PROJ_OBJ_ROOT)/Makefile.common
+
+CFLAGS = -O2 -fno-strict-aliasing
+
+CURDIR := $(shell cd .; pwd)
+PROGDIR := $(shell cd $(LLVM_SRC_ROOT)/projects/llvm-test; pwd)/
+RELDIR := $(subst $(PROGDIR),,$(CURDIR))
+GCCLD = $(LLVM_SRC_ROOT)/$(CONFIGURATION)/bin/gccld
+
+# Pool allocator pass shared object
+PA_SO := $(PROJECT_DIR)/Debug/lib/libaddchecks$(SHLIBEXT)
+
+# Pool allocator runtime library
+#PA_RT := $(PROJECT_DIR)/lib/Bytecode/libpoolalloc_fl_rt.bc
+#PA_RT_O := $(PROJECT_DIR)/$(CONFIGURATION)/lib/poolalloc_splay_rt.o
+PA_RT_O := $(PROJECT_DIR)/$(CONFIGURATION)/lib/poolalloc_safe_rt.o
+#PA_RT_O := $(PROJECT_DIR)/$(CONFIGURATION)/lib/libpoolalloc_splay_rt.bca
+#PA_RT_O := $(PROJECT_DIR)/$(CONFIGURATION)/lib/libpoolalloc_safe_rt.bca
+#PA_RT_O := $(PROJECT_DIR)/Release/lib/poolalloc_rt.o
+#PA_RT_O := $(PROJECT_DIR)/lib/Release/poolalloc_fl_rt.o
+
+# Command to run opt with the pool allocator pass loaded
+OPT_SC := $(LOPT) \
+ -load $(PROJECT_DIR)/../llvm-poolalloc/Debug/lib/poolalloc$(SHLIBEXT) \
+ -load $(PROJECT_DIR)/Debug/lib/libstackcheck$(SHLIBEXT) \
+ -load $(PROJECT_DIR)/Debug/lib/libarrayboundcheck$(SHLIBEXT) \
+ -load $(PROJECT_DIR)/Debug/lib/libconvert$(SHLIBEXT) \
+ -load $(PROJECT_DIR)/Debug/lib/libpointerchecks$(SHLIBEXT) \
+ -load $(PROJECT_DIR)/Debug/lib/libaddchecks$(SHLIBEXT) \
+
+
+# OPT_SC_STATS - Run opt with the -stats and -time-passes options, capturing the
+# output to a file.
+OPT_SC_STATS = $(OPT_SC) -info-output-file=$(CURDIR)/$@.info -stats -time-passes
+
+#OPTZN_PASSES := -globaldce -ipsccp -deadargelim -adce -instcombine -simplifycfg
+OPTZN_PASSES :=
+
+
+#
+# This rule runs SAFECode on the .llvm.bc file to produce a new .bc
+# file
+#
+$(PROGRAMS_TO_TEST:%=Output/%.$(TEST).bc): \
+Output/%.$(TEST).bc: Output/%.llvm.bc $(PA_SO) $(LOPT)
+ -@rm -f $(CURDIR)/$@.info
+ -$(OPT_SC_STATS) -abcpre -safecode $(OPTZN_PASSES) $< -o $@ -f 2>&1 > $@.out
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.bc): \
+Output/%.nonsc.bc: Output/%.llvm.bc $(LOPT)
+ -@rm -f $(CURDIR)/$@.info
+ -$(LOPT) $(OPTZN_PASSES) $< -o $@ -f 2>&1 > $@.out
+
+#
+# These rules compile the new .bc file into a .c file using CBE
+#
+$(PROGRAMS_TO_TEST:%=Output/%.safecode.cbe.c): \
+Output/%.safecode.cbe.c: Output/%.$(TEST).bc $(LLC)
+ -$(LLC) -march=c -f $< -o $@
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.cbe.c): \
+Output/%.nonsc.cbe.c: Output/%.nonsc.bc $(LLC)
+ -$(LLC) -march=c -f $< -o $@
+
+#
+# These rules compile the CBE .c file into a final executable
+#
+$(PROGRAMS_TO_TEST:%=Output/%.safecode.cbe): \
+Output/%.safecode.cbe: Output/%.safecode.cbe.c $(PA_RT_O)
+ -$(CC) -g $(CFLAGS) $< $(LLCLIBS) $(PA_RT_O) $(LDFLAGS) -o $@
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.cbe): \
+Output/%.nonsc.cbe: Output/%.nonsc.cbe.c $(PA_RT_O)
+ -$(CC) $(CFLAGS) $< $(LLCLIBS) $(LDFLAGS) -o $@
+
+
+
+ifndef PROGRAMS_HAVE_CUSTOM_RUN_RULES
+
+#
+# This rule runs the generated executable, generating timing information, for
+# normal test programs
+#
+$(PROGRAMS_TO_TEST:%=Output/%.safecode.out-cbe): \
+Output/%.safecode.out-cbe: Output/%.safecode.cbe
+ -$(RUNSAFELY) $(STDIN_FILENAME) $@ $< $(RUN_OPTIONS)
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.out-cbe): \
+Output/%.nonsc.out-cbe: Output/%.nonsc.cbe
+ -$(RUNSAFELY) $(STDIN_FILENAME) $@ $< $(RUN_OPTIONS)
+
+else
+
+#
+# This rule runs the generated executable, generating timing information, for
+# SPEC
+#
+$(PROGRAMS_TO_TEST:%=Output/%.safecode.out-cbe): \
+Output/%.safecode.out-cbe: Output/%.safecode.cbe
+ -$(SPEC_SANDBOX) safecodecbe-$(RUN_TYPE) $@ $(REF_IN_DIR) \
+ $(RUNSAFELY) $(STDIN_FILENAME) $(STDOUT_FILENAME) \
+ ../../$< $(RUN_OPTIONS)
+ -(cd Output/safecodecbe-$(RUN_TYPE); cat $(LOCAL_OUTPUTS)) > $@
+ -cp Output/safecodecbe-$(RUN_TYPE)/$(STDOUT_FILENAME).time $@.time
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.out-cbe): \
+Output/%.nonsc.out-cbe: Output/%.nonsc.cbe
+ -$(SPEC_SANDBOX) nonsccbe-$(RUN_TYPE) $@ $(REF_IN_DIR) \
+ $(RUNSAFELY) $(STDIN_FILENAME) $(STDOUT_FILENAME) \
+ ../../$< $(RUN_OPTIONS)
+ -(cd Output/nonsccbe-$(RUN_TYPE); cat $(LOCAL_OUTPUTS)) > $@
+ -cp Output/nonsccbe-$(RUN_TYPE)/$(STDOUT_FILENAME).time $@.time
+
+endif
+
+
+# This rule diffs the post-poolallocated version to make sure we didn't break
+# the program!
+$(PROGRAMS_TO_TEST:%=Output/%.safecode.diff-cbe): \
+Output/%.safecode.diff-cbe: Output/%.out-nat Output/%.safecode.out-cbe
+ @cp Output/$*.out-nat Output/$*.safecode.out-nat
+ -$(DIFFPROG) cbe $*.safecode $(HIDEDIFF)
+
+$(PROGRAMS_TO_TEST:%=Output/%.nonsc.diff-cbe): \
+Output/%.nonsc.diff-cbe: Output/%.out-nat Output/%.nonsc.out-cbe
+ @cp Output/$*.out-nat Output/$*.nonsc.out-nat
+ -$(DIFFPROG) cbe $*.nonsc $(HIDEDIFF)
+
+
+# This rule wraps everything together to build the actual output the report is
+# generated from.
+$(PROGRAMS_TO_TEST:%=Output/%.$(TEST).report.txt): \
+Output/%.$(TEST).report.txt: Output/%.out-nat \
+ Output/%.nonsc.diff-cbe \
+ Output/%.safecode.diff-cbe \
+ Output/%.LOC.txt
+ @echo > $@
+ @-if test -f Output/$*.nonsc.diff-cbe; then \
+ printf "GCC-RUN-TIME: " >> $@;\
+ grep "^program" Output/$*.out-nat.time >> $@;\
+ fi
+ @-if test -f Output/$*.nonsc.diff-cbe; then \
+ printf "CBE-RUN-TIME-NORMAL: " >> $@;\
+ grep "^program" Output/$*.nonsc.out-cbe.time >> $@;\
+ fi
+ @-if test -f Output/$*.safecode.diff-cbe; then \
+ printf "CBE-RUN-TIME-SAFECODE: " >> $@;\
+ grep "^program" Output/$*.safecode.out-cbe.time >> $@;\
+ fi
+ printf "LOC: " >> $@
+ cat Output/$*.LOC.txt >> $@
+ @cat Output/$*.$(TEST).bc.info >> $@
+
+$(PROGRAMS_TO_TEST:%=test.$(TEST).%): \
+test.$(TEST).%: Output/%.$(TEST).report.txt
+ @echo "---------------------------------------------------------------"
+ @echo ">>> ========= '$(RELDIR)/$*' Program"
+ @echo "---------------------------------------------------------------"
+ @cat $<
+
+REPORT_DEPENDENCIES := $(PA_RT_O) $(PA_SO) $(PROGRAMS_TO_TEST:%=Output/%.llvm.bc) $(LLC) $(LOPT)
diff --git a/safecode/test/TEST.safecode.report b/safecode/test/TEST.safecode.report
new file mode 100755
index 0000000..d24597e
--- /dev/null
+++ b/safecode/test/TEST.safecode.report
@@ -0,0 +1,95 @@
+##=== TEST.poolalloc.report - Report description for poolalloc -*- perl -*-===##
+#
+# This file defines a report to be generated for the pool allocator tests.
+#
+##===----------------------------------------------------------------------===##
+
+# Sort by program name
+$SortCol = 0;
+$TrimRepeatedPrefix = 1;
+
+# FormatTime - Convert a time from 1m23.45 into 83.45
+sub FormatTime {
+ my $Time = shift;
+ if ($Time =~ m/([0-9]+)[m:]([0-9.]+)/) {
+ return sprintf("%7.3f", $1*60.0+$2);
+ }
+
+ return sprintf("%6.2f", $Time);
+}
+
+
+sub RuntimePercent {
+ my ($Cols, $Col) = @_;
+ if ($Cols->[$Col-1] ne "*" and $Cols->[4] ne "*" and
+ $Cols->[4] != "0") {
+ return sprintf "%7.2f", 100*$Cols->[$Col-1]/$Cols->[4];
+ } else {
+ return "n/a";
+ }
+}
+
+@LatexColumns = (1, 5, 8, 12, 9, 13, 14, 15, 2, 16);
+
+my $FREEBENCH = 'MultiSource/Benchmarks/FreeBench';
+my $PTRDIST = 'MultiSource/Benchmarks/Ptrdist';
+
+@LatexRowMapOrder = (
+ '164.gzip/164.gzip' => '164.gzip',
+ '175.vpr/175.vpr' => '175.vpr',
+ '181.mcf/181.mcf' => '181.mcf',
+ '186.crafty/186.crafty' => '186.crafty',
+ '197.parser/197.parser' => '197.parser',
+ '197.parser.hacked/197.parser.hacked' => '197.parser(b)',
+ '255.vortex/255.vortex' => '255.vortex',
+ '256.bzip2/256.bzip2' => '256.bzip2',
+ '300.twolf/300.twolf' => '300.twolf',
+ '-' => '-',
+ "anagram/anagram" => 'anagram',
+ "bc/bc" => 'bc',
+ "ft/ft" => 'ft',
+ "ks/ks" => 'ks',
+ "yacr2/yacr2" => 'yacr2',
+ '-' => '-',
+ "analyzer" => 'analyzer',
+ "neural" => 'neural',
+ "pcompress2" => 'pcompress2',
+ "piff2" => 'piff2',
+ '-' => '-',
+ "bh/bh" => 'bh',
+ "bisort/bisort" => 'bisort',
+ "em3d/em3d" => 'em3d',
+ "health/health" => 'health',
+ "mst/mst" => 'mst',
+ "perimeter/perimeter" => 'perimeter',
+ "power/power" => 'power',
+ "treeadd/treeadd" => 'treeadd',
+ "tsp/tsp" => 'tsp',
+ '-' => '-',
+ "llu" => 'llu-bench',
+ );
+
+
+# These are the columns for the report. The first entry is the header for the
+# column, the second is the regex to use to match the value. Empty list create
+# seperators, and closures may be put in for custom processing.
+(
+# Name
+ ["Name:" , '\'([^\']+)\' Program'],
+ ["LOC" , 'LOC:\s*([0-9]+)'],
+ [],
+# Times
+ ["GCC", 'GCC-RUN-TIME: program\s*([.0-9m:]+)', \&FormatTime],
+ ["NonPATime", 'CBE-RUN-TIME-NORMAL: program\s*([.0-9m:]+)', \&FormatTime],
+ [],
+ ["SC Time", 'CBE-RUN-TIME-SAFECODE: program\s*([.0-9m:]+)', \&FormatTime],
+# ["NumPools", '([0-9]+).*Number of pools allocated'],
+# ["Typesafe", '([0-9]+).*Number of typesafe pools'],
+# ["BumpPtr", '([0-9]+).*Number of bump pointer pools'],
+# ["PFE", '([0-9]+).*Number of poolfree.s elided'],
+# ["NumArgs", '([0-9]+).*Number of function arguments added'],
+# ["MaxArgs", '([0-9]+).*Maximum function arguments added'],
+#["Nonprofit", '([0-9]+).*Number of DSNodes not profitable'],
+ []
+);
+
diff --git a/safecode/tools/EmbeC/Makefile b/safecode/tools/EmbeC/Makefile
new file mode 100755
index 0000000..38bb819
--- /dev/null
+++ b/safecode/tools/EmbeC/Makefile
@@ -0,0 +1,10 @@
+LEVEL = ../..
+TOOLNAME = embec
+LLVMLIBS = bcreader bcwriter instrument \
+ profpaths scalaropts \
+ ipo ipa.a datastructure.a transforms target.a analysis \
+ transformutils vmcore support cwriter
+USEDLIBS = pointerchecks arrayboundcheck.a omega_calc.a code_gen.a omega.a
+TOOLLINKOPTSB = -L/home/vadve/dhurjati/libs
+TOOLLINKOPTS = -ldl -lm
+include $(LEVEL)/Makefile.common
diff --git a/safecode/tools/EmbeC/embec.cpp b/safecode/tools/EmbeC/embec.cpp
new file mode 100755
index 0000000..509f59b
--- /dev/null
+++ b/safecode/tools/EmbeC/embec.cpp
@@ -0,0 +1,84 @@
+//===----------------------------------------------------------------------===//
+// LLVM 'embec' UTILITY : Checks codes for safety as per the EmbeC language
+// rules. Targetted at embedded systems.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Bytecode/Reader.h"
+#include "llvm/Assembly/CWriter.h"
+#include "UninitPointer.h"
+#include "SafeDynMemAlloc.h"
+#include "ArrayBoundsCheck.h"
+#include "StackSafety.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Target/TargetData.h"
+#include "Support/CommandLine.h"
+#include "Support/Signals.h"
+#include <fstream>
+#include <memory>
+using namespace std;
+
+static cl::opt<string>
+InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-"));
+
+static cl::opt<string>
+OutputFilename("o", cl::desc("Override output filename"),
+ cl::value_desc("filename"));
+
+static cl::opt<bool>
+Force("f", cl::desc("Overwrite output files"));
+
+int main(int argc, char **argv) {
+
+ cl::ParseCommandLineOptions(argc, argv,
+ " llvm .bc -> .bc modular optimizer\n");
+
+ // Load the input module...
+ std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename));
+
+
+ if (M.get() == 0) {
+ cerr << "bytecode didn't read correctly.\n";
+ return 1;
+ }
+
+ // Figure out what stream we are supposed to write to...
+
+ std::ostream *Out = &std::cout; // Default to printing to stdout...
+
+
+ if (OutputFilename != "") {
+ Out = new std::ofstream(OutputFilename.c_str());
+
+
+ if (!Out->good()) {
+ cerr << "Error opening " << OutputFilename << "!\n";
+ return 1;
+ }
+
+ }
+
+
+ //
+ PassManager Passes;
+ Passes.add(new TargetData("embec", M.get()));
+
+ //Add passes
+ Passes.add(createCZeroUninitPtrPass());
+ /*
+ Passes.add(createABCPreProcessPass());
+ Passes.add(createArrayBoundsCheckPass());
+ Passes.add(createStackSafetyPass());
+ */
+ Passes.add(createEmbeCFreeRemovalPass());
+
+ // Now that we have all of the passes ready, run them.
+ if (Passes.run(*M.get()))
+ cerr << "Program modified.\n";
+ (*Out) << M.get();
+ // WriteToC(M.get(), *Out, false);
+
+ return 0;
+}
diff --git a/safecode/tools/Makefile b/safecode/tools/Makefile
new file mode 100755
index 0000000..2244d19
--- /dev/null
+++ b/safecode/tools/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ..
+PARALLEL_DIRS =
+
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/tools/Parse/Makefile b/safecode/tools/Parse/Makefile
new file mode 100755
index 0000000..43837c0
--- /dev/null
+++ b/safecode/tools/Parse/Makefile
@@ -0,0 +1,10 @@
+LEVEL = ../..
+TOOLNAME = parse
+LLVMLIBS = bcreader bcwriter instrument profpaths scalaropts \
+ ipo ipa.a datastructure.a transforms target.a analysis \
+ transformutils vmcore support cwriter
+USEDLIBS = arrayboundcheck.a omega_calc.a codegen.a omega.a
+TOOLLINKOPTSB = -L/home/vadve/dhurjati/libs
+TOOLLINKOPTS = -ldl -lm
+include $(LEVEL)/Makefile.common
+
diff --git a/safecode/tools/Parse/parse.cpp b/safecode/tools/Parse/parse.cpp
new file mode 100755
index 0000000..99708dc
--- /dev/null
+++ b/safecode/tools/Parse/parse.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+// LLVM 'czero' UTILITY
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Bytecode/Reader.h"
+#include "llvm/Assembly/CWriter.h"
+#include "ArrayBoundsCheck.h"
+#include "llvm/Transforms/Scalar.h"
+#include "Support/CommandLine.h"
+#include "Support/Signals.h"
+#include <fstream>
+#include <memory>
+using namespace std;
+
+static cl::opt<string>
+InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-"));
+
+static cl::opt<string>
+OutputFilename("o", cl::desc("Override output filename"),
+ cl::value_desc("filename"));
+
+static cl::opt<bool>
+Force("f", cl::desc("Overwrite output files"));
+
+int main(int argc, char **argv) {
+
+ cl::ParseCommandLineOptions(argc, argv,
+ " llvm .bc -> .bc modular optimizer\n");
+
+// Load the input module...
+ std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename));
+
+
+ if (M.get() == 0) {
+ cerr << "bytecode didn't read correctly.\n";
+ return 1;
+ }
+
+ // Figure out what stream we are supposed to write to...
+
+ std::ostream *Out = &std::cout; // Default to printing to stdout...
+
+
+ if (OutputFilename != "") {
+ Out = new std::ofstream(OutputFilename.c_str());
+
+ if (!Out->good()) {
+ cerr << "Error opening " << OutputFilename << "!\n";
+ return 1;
+ }
+
+ }
+
+
+ //
+ PassManager Passes;
+
+ //Add passes
+ Passes.add(createABCPreProcessPass());
+ // Passes.add(createPiNodeInsertionPass());
+ Passes.add(createArrayBoundsCheckPass());
+
+ // Now that we have all of the passes ready, run them.
+ Passes.run(*M.get());
+ (*Out) << M.get();
+ // WriteToC(M.get(), *Out, false);
+
+ return 0;
+}