--- /dev/null
+# Generated automatically from Makefile.in by configure.
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id: Makefile 132 1999-09-27 15:54:42Z chris $
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = .
+prefix = /usr/local/cacao
+exec_prefix = ${prefix}
+
+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
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/cacao
+pkglibdir = $(libdir)/cacao
+pkgincludedir = $(includedir)/cacao
+
+top_builddir = .
+
+ACLOCAL = aclocal
+AUTOCONF = autoconf
+AUTOMAKE = automake
+AUTOHEADER = autoheader
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+transform = s,x,x,
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = alpha-unknown-linux
+host_triplet = alpha-unknown-linux-gnu
+CC = gcc
+COMPILER_OBJECTS = compiler.o
+COMPILER_SOURCES = compiler.h compiler.c
+GC_OBJ = mm/libmm_new.a
+LIBTHREAD = libthreads.a
+MAKEINFO = makeinfo
+PACKAGE = cacao
+RANLIB = ranlib
+SYSDEP_DIR = alpha
+THREAD_OBJ = threads/libthreads.a
+VERSION = 0.40
+
+MAINTAINERCLEANFILES = Makefile.in configure
+SUBDIRS = toolbox mm alpha jit comp nat threads mips tst doc narray
+
+EXTRA_DIST = html/cacaoinstall.html html/cacaoman.html html/index.html
+
+CLEANFILES = alpha/asmpart.o \
+ alpha/asmpart.s \
+ alpha/offsets.h \
+ nativetable.hh \
+ nativetypes.hh
+
+bin_PROGRAMS = cacao
+noinst_PROGRAMS = cacaoh
+
+INCLUDES=-I/usr/include -I$(top_srcdir)/alpha -I$(top_srcdir)/jit -Ialpha -I$(top_srcdir)
+
+cacao_SOURCES = \
+ asmpart.h \
+ builtin.c \
+ builtin.h \
+ callargs.h \
+ compiler.h compiler.c \
+ global.h \
+ jit.c \
+ jit.h \
+ loader.c \
+ loader.h \
+ main.c \
+ native.c \
+ native.h \
+ tables.c \
+ tables.h
+
+EXTRA_cacao_SOURCES = \
+ compiler.c \
+ compiler.h
+
+cacao_LDADD = \
+ alpha/asmpart.o \
+ compiler.o \
+ toolbox/libtoolbox.a \
+ mm/libmm_new.a \
+ threads/libthreads.a
+
+cacao_DEPENDENCIES = \
+ alpha/asmpart.o \
+ compiler.o \
+ toolbox/libtoolbox.a \
+ mm/libmm_new.a \
+ threads/libthreads.a
+
+cacaoh_SOURCES = headers.c tables.c loader.c builtin.c
+cacaoh_LDADD = toolbox/libtoolbox.a mm/libmm_new.a threads/libthreads.a
+cacaoh_DEPENDENCIES = toolbox/libtoolbox.a mm/libmm_new.a threads/libthreads.a
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+
+
+DEFS = -DHAVE_CONFIG_H -I. -I$(srcdir) -I.
+CPPFLAGS =
+LDFLAGS =
+LIBS = -lm
+cacao_OBJECTS = builtin.o jit.o loader.o main.o native.o tables.o
+cacao_LDFLAGS =
+cacaoh_OBJECTS = headers.o tables.o loader.o builtin.o
+cacaoh_LDFLAGS =
+CFLAGS = -ieee -O2 -g3
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
+Makefile.in NEWS acconfig.h aclocal.m4 config.guess config.h.in \
+config.sub configure configure.in install-sh missing mkinstalldirs \
+stamp-h.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+DEP_FILES = .deps/builtin.P .deps/compiler.P .deps/headers.P \
+.deps/jit.P .deps/loader.P .deps/main.P .deps/native.P .deps/tables.P
+SOURCES = $(cacao_SOURCES) $(EXTRA_cacao_SOURCES) $(cacaoh_SOURCES)
+OBJECTS = $(cacao_OBJECTS) $(cacaoh_OBJECTS)
+
+all: all-recursive-am all-am
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): configure.in
+ cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure
+ $(SHELL) ./config.status --recheck
+$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+ cd $(srcdir) && $(AUTOCONF)
+
+config.h: stamp-h
+ @:
+stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES= CONFIG_HEADERS=config.h \
+ $(SHELL) ./config.status
+ @echo timestamp > stamp-h
+$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
+ cd $(top_srcdir) && $(AUTOHEADER)
+ @echo timestamp > $(srcdir)/stamp-h.in
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+ -rm -f config.h
+
+maintainer-clean-hdr:
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+ done
+
+mostlyclean-noinstPROGRAMS:
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+
+distclean-noinstPROGRAMS:
+
+maintainer-clean-noinstPROGRAMS:
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+cacao: $(cacao_OBJECTS) $(cacao_DEPENDENCIES)
+ @rm -f cacao
+ $(LINK) $(cacao_LDFLAGS) $(cacao_OBJECTS) $(cacao_LDADD) $(LIBS)
+
+cacaoh: $(cacaoh_OBJECTS) $(cacaoh_DEPENDENCIES)
+ @rm -f cacaoh
+ $(LINK) $(cacaoh_LDFLAGS) $(cacaoh_OBJECTS) $(cacaoh_LDADD) $(LIBS)
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ target=`echo $@ | sed s/-recursive//`; \
+ echo "Making $$target in $$subdir"; \
+ (cd $$subdir && $(MAKE) $$target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done && test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+ rev="$$subdir $$rev"; \
+ done; \
+ for subdir in $$rev; do \
+ target=`echo $@ | sed s/-recursive//`; \
+ echo "Making $$target in $$subdir"; \
+ (cd $$subdir && $(MAKE) $$target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ (cd $$subdir && $(MAKE) tags); \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+ done; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ -rm -rf $(distdir)
+ GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz
+ mkdir $(distdir)/=build
+ mkdir $(distdir)/=inst
+ dc_install_base=`cd $(distdir)/=inst && pwd`; \
+ cd $(distdir)/=build \
+ && ../configure --srcdir=.. --prefix=$$dc_install_base \
+ && $(MAKE) \
+ && $(MAKE) dvi \
+ && $(MAKE) check \
+ && $(MAKE) install \
+ && $(MAKE) installcheck \
+ && $(MAKE) dist
+ -rm -rf $(distdir)
+ @echo "========================"; \
+ echo "$(distdir).tar.gz is ready for distribution"; \
+ echo "========================"
+dist: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+dist-all: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+distdir: $(DISTFILES)
+ -rm -rf $(distdir)
+ mkdir $(distdir)
+ -chmod 777 $(distdir)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile
+ $(mkinstalldirs) $(distdir)/html
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+ for subdir in $(SUBDIRS); do \
+ test -d $(distdir)/$$subdir \
+ || mkdir $(distdir)/$$subdir \
+ || exit 1; \
+ chmod 777 $(distdir)/$$subdir; \
+ (cd $$subdir && $(MAKE) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+ || exit 1; \
+ done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+ -rm -rf .deps
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+ @-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+ < .deps/$(*F).p > .deps/$(*F).P
+ @-rm -f .deps/$(*F).p
+info: info-recursive
+dvi: dvi-recursive
+check: all-am
+ $(MAKE) check-recursive
+installcheck: installcheck-recursive
+all-recursive-am: config.h
+ $(MAKE) all-recursive
+
+all-am: Makefile $(PROGRAMS) config.h
+
+install-exec-am: install-binPROGRAMS
+
+uninstall-am: uninstall-binPROGRAMS
+
+install-exec: install-exec-recursive install-exec-am
+ @$(NORMAL_INSTALL)
+
+install-data: install-data-recursive
+ @$(NORMAL_INSTALL)
+
+install: install-recursive install-exec-am
+ @:
+
+uninstall: uninstall-recursive uninstall-am
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs: installdirs-recursive
+ $(mkinstalldirs) $(DATADIR)$(bindir)
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(DISTCLEANFILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \
+ mostlyclean-noinstPROGRAMS mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+clean-am: clean-hdr clean-binPROGRAMS clean-noinstPROGRAMS \
+ clean-compile clean-tags clean-depend clean-generic \
+ mostlyclean-am
+
+distclean-am: distclean-hdr distclean-binPROGRAMS \
+ distclean-noinstPROGRAMS distclean-compile \
+ distclean-tags distclean-depend distclean-generic \
+ clean-am
+
+maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \
+ maintainer-clean-noinstPROGRAMS \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean-am
+
+mostlyclean: mostlyclean-recursive mostlyclean-am
+
+clean: clean-recursive clean-am
+
+distclean: distclean-recursive distclean-am
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-recursive maintainer-clean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \
+clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile install-data-recursive \
+uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck all-recursive-am all-am \
+install-exec-am uninstall-am install-exec install-data install \
+uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
+
+
+native.c: nativetypes.hh alpha/offsets.h nativetable.hh
+
+nativetypes.hh alpha/offsets.h nativetable.hh: cacaoh
+ ./cacaoh \
+ java.lang.Object \
+ java.lang.String \
+ java.lang.Class \
+ java.lang.ClassLoader \
+ java.lang.Compiler \
+ java.lang.Double \
+ java.lang.Float \
+ java.lang.Math \
+ java.lang.Runtime \
+ java.lang.SecurityManager \
+ java.lang.System \
+ java.lang.Thread \
+ java.lang.ThreadGroup \
+ java.lang.Throwable \
+ java.io.File \
+ java.io.FileDescriptor \
+ java.io.FileInputStream \
+ java.io.FileOutputStream \
+ java.io.PrintStream \
+ java.io.RandomAccessFile \
+ java.util.Properties \
+ java.util.Date
+
+alpha/asmpart.o: $(top_srcdir)/alpha/asmpart.c alpha/offsets.h
+ rm -f alpha/asmpart.s
+ gcc -E $(INCLUDES) $(top_srcdir)/alpha/asmpart.c \
+ > alpha/asmpart.s
+ gcc $(CFLAGS) $(INCLUDES) -c -o alpha/asmpart.o \
+ alpha/asmpart.s
+ rm -f asmpart.s
+
+compiler.o: $(top_srcdir)/builtin.h $(top_srcdir)/compiler.h \
+ $(top_srcdir)/global.h $(top_srcdir)/loader.h \
+ $(top_srcdir)/tables.h $(top_srcdir)/native.h \
+ $(top_srcdir)/asmpart.h $(top_srcdir)/compiler.c $(top_srcdir)/comp/*.c \
+ $(top_srcdir)/alpha/gen.c $(top_srcdir)/alpha/disass.c
+ gcc $(CFLAGS) -I. $(INCLUDES) -c $(top_srcdir)/compiler.c
+
+jit.o: jit.c \
+ jit/mcode.c \
+ jit/parse.c \
+ jit/reg.c \
+ jit/stack.c \
+ jit/jitdef.h \
+ narray/graph.c \
+ narray/loop.c \
+ narray/analyze.c \
+ narray/tracing.c \
+ narray/loop.h
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
-# $Id: Makefile.in 128 1999-03-03 15:54:06Z phil $
+# $Id: Makefile.in 132 1999-09-27 15:54:42Z chris $
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
VERSION = @VERSION@
MAINTAINERCLEANFILES = Makefile.in configure
-SUBDIRS = toolbox mm alpha jit comp nat threads mips tst doc
+SUBDIRS = toolbox mm alpha jit comp nat threads mips tst doc narray
EXTRA_DIST = html/cacaoinstall.html html/cacaoman.html html/index.html
-CLEANFILES = @SYSDEP_DIR@/asmpart.o @SYSDEP_DIR@/asmpart.s @SYSDEP_DIR@/offsets.h nativetable.hh nativetypes.hh
-
+CLEANFILES = @SYSDEP_DIR@/asmpart.o \
+ @SYSDEP_DIR@/asmpart.s \
+ @SYSDEP_DIR@/offsets.h \
+ nativetable.hh \
+ nativetypes.hh
bin_PROGRAMS = cacao
noinst_PROGRAMS = cacaoh
+<<<<<<< Makefile.in
+
+INCLUDES=-I/usr/include -I$(top_srcdir)/@SYSDEP_DIR@ -I$(top_srcdir)/jit -I@SYSDEP_DIR@ -I$(top_srcdir)
+=======
INCLUDES = -I/usr/include -I$(top_srcdir)/@SYSDEP_DIR@ -I$(top_srcdir)/jit -I@SYSDEP_DIR@ -I$(top_srcdir)
cacao_LDADD = @SYSDEP_DIR@/asmpart.o @COMPILER_OBJECTS@ toolbox/libtoolbox.a @GC_OBJ@ @THREAD_OBJ@
-
-
-cacao_DEPENDENCIES = @SYSDEP_DIR@/asmpart.o @COMPILER_OBJECTS@ toolbox/libtoolbox.a @GC_OBJ@ @THREAD_OBJ@
-
+>>>>>>> 3.10
+
+cacao_SOURCES = \
+ asmpart.h \
+ builtin.c \
+ builtin.h \
+ callargs.h \
+ @COMPILER_SOURCES@ \
+ global.h \
+ jit.c \
+ jit.h \
+ loader.c \
+ loader.h \
+ main.c \
+ native.c \
+ native.h \
+ tables.c \
+ tables.h
+
+EXTRA_cacao_SOURCES = \
+ compiler.c \
+ compiler.h
+
+cacao_LDADD = \
+ @SYSDEP_DIR@/asmpart.o \
+ @COMPILER_OBJECTS@ \
+ toolbox/libtoolbox.a \
+ @GC_OBJ@ \
+ @THREAD_OBJ@
+
+cacao_DEPENDENCIES = \
+ @SYSDEP_DIR@/asmpart.o \
+ @COMPILER_OBJECTS@ \
+ toolbox/libtoolbox.a \
+ @GC_OBJ@ \
+ @THREAD_OBJ@
cacaoh_SOURCES = headers.c tables.c loader.c builtin.c
cacaoh_LDADD = toolbox/libtoolbox.a @GC_OBJ@ @THREAD_OBJ@
cacaoh_OBJECTS = headers.o tables.o loader.o builtin.o
cacaoh_LDFLAGS =
CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
-DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog INSTALL \
-Makefile.am Makefile.in NEWS acconfig.h aclocal.m4 config.guess \
-config.h.in config.sub configure configure.in install-sh missing \
-mkinstalldirs
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
+Makefile.in NEWS acconfig.h aclocal.m4 config.guess config.h.in \
+config.sub configure configure.in install-sh missing mkinstalldirs \
+stamp-h.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
+GZIP = --best
+DEP_FILES = .deps/builtin.P .deps/compiler.P .deps/headers.P \
+.deps/jit.P .deps/loader.P .deps/main.P .deps/native.P .deps/tables.P
SOURCES = $(cacao_SOURCES) $(EXTRA_cacao_SOURCES) $(cacaoh_SOURCES)
OBJECTS = $(cacao_OBJECTS) $(cacaoh_OBJECTS)
-all: all-redirect
+all: all-recursive-am all-am
+
.SUFFIXES:
.SUFFIXES: .S .c .o .s
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): configure.in
cd $(srcdir) && $(ACLOCAL)
-config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+config.status: $(srcdir)/configure
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
config.h: stamp-h
- @if test ! -f $@; then \
- rm -f stamp-h; \
- $(MAKE) stamp-h; \
- else :; fi
+ @:
stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES= CONFIG_HEADERS=config.h \
$(SHELL) ./config.status
- @echo timestamp > stamp-h 2> /dev/null
+ @echo timestamp > stamp-h
$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
- @if test ! -f $@; then \
- rm -f $(srcdir)/stamp-h.in; \
- $(MAKE) $(srcdir)/stamp-h.in; \
- else :; fi
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
cd $(top_srcdir) && $(AUTOHEADER)
- @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+ @echo timestamp > $(srcdir)/stamp-h.in
mostlyclean-hdr:
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
- echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
- $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
list='$(bin_PROGRAMS)'; for p in $$list; do \
- rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
done
mostlyclean-noinstPROGRAMS:
maintainer-clean-noinstPROGRAMS:
-.c.o:
- $(COMPILE) -c $<
-
.s.o:
$(COMPILE) -c $<
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
+ target=`echo $@ | sed s/-recursive//`; \
echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- dot_seen=yes; \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ (cd $$subdir && $(MAKE) $$target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
- done; \
- if test "$$dot_seen" = "no"; then \
- $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
- fi; test -z "$$fail"
+ done && test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
- dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
- test "$$subdir" = "." && dot_seen=yes; \
done; \
- test "$$dot_seen" = "no" && rev=". $$rev"; \
- target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
+ target=`echo $@ | sed s/-recursive//`; \
echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ (cd $$subdir && $(MAKE) $$target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ (cd $$subdir && $(MAKE) tags); \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
- && mkid -f$$here/ID $$unique $(LISP)
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
- fi; \
+ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
done; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
# tarfile.
distcheck: dist
-rm -rf $(distdir)
- GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+ GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
- && $(MAKE) $(AM_MAKEFLAGS) \
- && $(MAKE) $(AM_MAKEFLAGS) dvi \
- && $(MAKE) $(AM_MAKEFLAGS) check \
- && $(MAKE) $(AM_MAKEFLAGS) install \
- && $(MAKE) $(AM_MAKEFLAGS) installcheck \
- && $(MAKE) $(AM_MAKEFLAGS) dist
+ && $(MAKE) \
+ && $(MAKE) dvi \
+ && $(MAKE) check \
+ && $(MAKE) install \
+ && $(MAKE) installcheck \
+ && $(MAKE) dist
-rm -rf $(distdir)
- @banner="$(distdir).tar.gz is ready for distribution"; \
- dashes=`echo "$$banner" | sed s/./=/g`; \
- echo "$$dashes"; \
- echo "$$banner"; \
- echo "$$dashes"
+ @echo "========================"; \
+ echo "$(distdir).tar.gz is ready for distribution"; \
+ echo "========================"
dist: distdir
-chmod -R a+r $(distdir)
- GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
- GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile
$(mkinstalldirs) $(distdir)/html
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
for subdir in $(SUBDIRS); do \
- if test "$$subdir" = .; then :; else \
- test -d $(distdir)/$$subdir \
- || mkdir $(distdir)/$$subdir \
+ test -d $(distdir)/$$subdir \
+ || mkdir $(distdir)/$$subdir \
+ || exit 1; \
+ chmod 777 $(distdir)/$$subdir; \
+ (cd $$subdir && $(MAKE) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
- chmod 777 $(distdir)/$$subdir; \
- (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
- || exit 1; \
- fi; \
done
-info-am:
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+ -rm -rf .deps
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+ @-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+ < .deps/$(*F).p > .deps/$(*F).P
+ @-rm -f .deps/$(*F).p
info: info-recursive
-dvi-am:
dvi: dvi-recursive
-check-am: all-am
-check: check-recursive
-installcheck-am:
+check: all-am
+ $(MAKE) check-recursive
installcheck: installcheck-recursive
all-recursive-am: config.h
- $(MAKE) $(AM_MAKEFLAGS) all-recursive
+ $(MAKE) all-recursive
+
+all-am: Makefile $(PROGRAMS) config.h
install-exec-am: install-binPROGRAMS
-install-exec: install-exec-recursive
-install-data-am:
+uninstall-am: uninstall-binPROGRAMS
+
+install-exec: install-exec-recursive install-exec-am
+ @$(NORMAL_INSTALL)
+
install-data: install-data-recursive
+ @$(NORMAL_INSTALL)
+
+install: install-recursive install-exec-am
+ @:
+
+uninstall: uninstall-recursive uninstall-am
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-recursive
-uninstall-am: uninstall-binPROGRAMS
-uninstall: uninstall-recursive
-all-am: Makefile $(PROGRAMS) config.h
-all-redirect: all-recursive-am
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs: installdirs-recursive
-installdirs-am:
- $(mkinstalldirs) $(DESTDIR)$(bindir)
+ $(mkinstalldirs) $(DATADIR)$(bindir)
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \
mostlyclean-noinstPROGRAMS mostlyclean-compile \
- mostlyclean-tags mostlyclean-generic
-
-mostlyclean: mostlyclean-recursive
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
clean-am: clean-hdr clean-binPROGRAMS clean-noinstPROGRAMS \
- clean-compile clean-tags clean-generic mostlyclean-am
-
-clean: clean-recursive
+ clean-compile clean-tags clean-depend clean-generic \
+ mostlyclean-am
distclean-am: distclean-hdr distclean-binPROGRAMS \
distclean-noinstPROGRAMS distclean-compile \
- distclean-tags distclean-generic clean-am
-
-distclean: distclean-recursive
- -rm -f config.status
+ distclean-tags distclean-depend distclean-generic \
+ clean-am
maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \
maintainer-clean-noinstPROGRAMS \
maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-generic distclean-am
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean-am
+
+mostlyclean: mostlyclean-recursive mostlyclean-am
+
+clean: clean-recursive clean-am
+
+distclean: distclean-recursive distclean-am
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-recursive maintainer-clean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-
-maintainer-clean: maintainer-clean-recursive
-rm -f config.status
.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
all-recursive check-recursive installcheck-recursive info-recursive \
dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
-distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
-dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
-install-exec-am install-exec install-data-am install-data install-am \
-install uninstall-am uninstall all-redirect all-am all installdirs-am \
-installdirs mostlyclean-generic distclean-generic clean-generic \
-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info dvi installcheck all-recursive-am all-am \
+install-exec-am uninstall-am install-exec install-data install \
+uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
native.c: nativetypes.hh @SYSDEP_DIR@/offsets.h nativetable.hh
@SYSDEP_DIR@/asmpart.s
rm -f asmpart.s
-compiler.o: builtin.h compiler.h global.h loader.h tables.h native.h \
- asmpart.h compiler.c comp/*.c \
- @SYSDEP_DIR@/gen.c @SYSDEP_DIR@/disass.c
- @CC@ $(CFLAGS) $(INCLUDES) -c compiler.c
+compiler.o: $(top_srcdir)/builtin.h $(top_srcdir)/compiler.h \
+ $(top_srcdir)/global.h $(top_srcdir)/loader.h \
+ $(top_srcdir)/tables.h $(top_srcdir)/native.h \
+ $(top_srcdir)/asmpart.h $(top_srcdir)/compiler.c $(top_srcdir)/comp/*.c \
+ $(top_srcdir)/@SYSDEP_DIR@/gen.c $(top_srcdir)/@SYSDEP_DIR@/disass.c
+ @CC@ $(CFLAGS) -I. $(INCLUDES) -c $(top_srcdir)/compiler.c
+<<<<<<< Makefile.in
+jit.o: jit.c \
+ jit/mcode.c \
+ jit/parse.c \
+ jit/reg.c \
+ jit/stack.c \
+ jit/jitdef.h \
+ narray/graph.c \
+ narray/loop.c \
+ narray/analyze.c \
+ narray/tracing.c \
+ narray/loop.h
+
+=======
jit.o: jit.c \
jit/mcode.c \
jit/parse.c \
jit/stack.c \
jit/jitdef.h
+>>>>>>> 3.10
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
-dnl aclocal.m4 generated automatically by aclocal 1.4
+dnl aclocal.m4 generated automatically by aclocal 1.3
-dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
+dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+dnl This Makefile.in is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
-[AC_REQUIRE([AC_PROG_INSTALL])
+[AC_REQUIRE([AM_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
-AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
-AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION"))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+# serial 1
+
+AC_DEFUN(AM_PROG_INSTALL,
+[AC_REQUIRE([AC_PROG_INSTALL])
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+AC_SUBST(INSTALL_SCRIPT)dnl
+])
+
#
# Check to make sure that the build environment is sane.
#
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
THREAD_OBJ = @THREAD_OBJ@
VERSION = @VERSION@
-EXTRA_DIST = asmpart.c disass.c cray.c gen.c ngen.c defines.h native-math.h ngen.h sigcontext.h types.h threads.h
-
+EXTRA_DIST = asmpart.c disass.c cray.c gen.c ngen.c \
+ defines.h native-math.h ngen.h sigcontext.h \
+ types.h threads.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
-all: all-redirect
+GZIP = --best
+all: Makefile
+
.SUFFIXES:
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps alpha/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu alpha/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
subdir = alpha
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu alpha/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile
-all-redirect: all-am
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-generic
-
-mostlyclean: mostlyclean-am
-
-clean-am: clean-generic mostlyclean-am
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-generic
-clean: clean-am
+clean: clean-generic mostlyclean
-distclean-am: distclean-generic clean-am
+distclean: distclean-generic clean
+ -rm -f config.status
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-generic distclean-am
+maintainer-clean: maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
-.PHONY: tags distdir info-am info dvi-am dvi check check-am \
-installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+.PHONY: tags distdir info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
- Last Change: $Id: ngen.c 115 1999-01-20 01:52:45Z phil $
+ Last Change: $Id: ngen.c 132 1999-09-27 15:54:42Z chris $
*******************************************************************************/
/* additional functions and macros to generate code ***************************/
-#define BlockPtrOfPC(pc) block+block_index[pc]
+/* #define BlockPtrOfPC(pc) block+block_index[pc] */
+#define BlockPtrOfPC(pc) ((basicblock *) iptr->target)
+
#ifdef STATISTICS
#define COUNT_SPILLS count_spills++
varinfo *var;
basicblock *bptr;
instruction *iptr;
+ xtable *ex;
{
int p, pa, t, l, r;
(void) dseg_adds4(exceptiontablelength); /* ExTableSize */
/* create exception table */
-
- for (len = 0; len < exceptiontablelength; len++) {
- dseg_addtarget(BlockPtrOfPC(extable[len].startpc));
- dseg_addtarget(BlockPtrOfPC(extable[len].endpc));
- dseg_addtarget(BlockPtrOfPC(extable[len].handlerpc));
- (void) dseg_addaddress(extable[len].catchtype);
+
+ for (ex = extable; ex != NULL; ex = ex->down) {
+
+#ifdef LOOP_DEBUG
+ if (ex->start != NULL)
+ printf("adding start - %d - ", ex->start->debug_nr);
+ else {
+ printf("PANIC - start is NULL");
+ exit(-1);
}
+#endif
+
+ dseg_addtarget(ex->start);
+
+#ifdef LOOP_DEBUG
+ if (ex->end != NULL)
+ printf("adding end - %d - ", ex->end->debug_nr);
+ else {
+ printf("PANIC - end is NULL");
+ exit(-1);
+ }
+#endif
+ dseg_addtarget(ex->end);
+
+#ifdef LOOP_DEBUG
+ if (ex->handler != NULL)
+ printf("adding handler - %d\n", ex->handler->debug_nr);
+ else {
+ printf("PANIC - handler is NULL");
+ exit(-1);
+ }
+#endif
+
+ dseg_addtarget(ex->handler);
+
+ (void) dseg_addaddress(ex->catchtype);
+ }
+
/* initialize mcode variables */
mcodeptr = (s4*) mcodebase;
/* end of header generation */
/* walk through all basic blocks */
+ for (/* bbs = block_count, */ bptr = block; /* --bbs >= 0 */ bptr != NULL; bptr = bptr->next) {
- for (bbs = block_count, bptr = block; --bbs >= 0; bptr++) {
bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
if (bptr->flags >= BBREACHED) {
}
/* walk through all instructions */
-
+
src = bptr->instack;
len = bptr->icount;
for (iptr = bptr->iinstr;
/* memory operations **************************************************/
-#define gen_bound_check \
+ /* #define gen_bound_check \
if (checkbounds) {\
M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
M_BEQZ(REG_ITMP3, 0);\
mcode_addxboundrefs(mcodeptr);\
}
+ */
+
+#define gen_bound_check \
+ if (checkbounds) { \
+ M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
+ M_CMPULT(s2, REG_ITMP3, REG_ITMP3);\
+ M_BEQZ(REG_ITMP3, 0);\
+ mcode_addxboundrefs(mcodeptr); \
+ }
case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
gen_nullptr_check(s1);
gen_bound_check;
}
+
M_S4ADDQ(s2, s1, REG_ITMP1);
M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
store_reg_to_var_int(iptr->dst, d);
gen_nullptr_check(s1);
gen_bound_check;
}
+
var_to_reg_int(s3, src, REG_ITMP3);
M_S4ADDQ(s2, s1, REG_ITMP1);
M_IST (s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
case ICMD_TABLESWITCH: /* ..., index ==> ... */
{
s4 i, l, *s4ptr;
+ void **tptr;
+
+ tptr = (void **) iptr->target;
s4ptr = iptr->val.a;
l = s4ptr[1]; /* low */
M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
}
M_BEQZ(REG_ITMP2, 0);
- mcode_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr);
+
+
+ /* mcode_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
+ mcode_addreference((basicblock *) tptr[0], mcodeptr);
/* build jump table top down and use address of lowest entry */
- s4ptr += 3 + i;
+ /* s4ptr += 3 + i; */
+ tptr += i;
+
while (--i >= 0) {
- dseg_addtarget(BlockPtrOfPC(*--s4ptr));
+ /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
+ dseg_addtarget((basicblock *) tptr[0]);
+ --tptr;
}
}
case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
{
s4 i, l, val, *s4ptr;
+ void **tptr;
+
+ tptr = (void **) iptr->target;
s4ptr = iptr->val.a;
l = s4ptr[0]; /* default */
var_to_reg_int(s1, src, REG_ITMP1);
while (--i >= 0) {
s4ptr += 2;
+ ++tptr;
+
val = s4ptr[0];
if ((val >= 0) && (val <= 255)) {
M_CMPEQ_IMM(s1, val, REG_ITMP2);
M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
}
M_BNEZ(REG_ITMP2, 0);
- mcode_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr);
+ /* mcode_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
+ mcode_addreference((basicblock *) tptr[0], mcodeptr);
}
M_BR(0);
- mcode_addreference(BlockPtrOfPC(l), mcodeptr);
+ /* mcode_addreference(BlockPtrOfPC(l), mcodeptr); */
+
+ tptr = (void **) iptr->target;
+ mcode_addreference((basicblock *) tptr[0], mcodeptr);
+
ALIGNCODENOP;
break;
}
while (ml < -32768) {ml += 65536; mh--;}
M_LDA(REG_PV, REG_RA, ml);
M_LDAH(REG_PV, REG_PV, mh);
- }
+ }
s1 = reg_of_var(iptr->dst, REG_RESULT);
M_INTMOVE(REG_RESULT, s1);
store_reg_to_var_int(iptr->dst, s1);
default: sprintf (logtext, "Unknown pseudo command: %d", iptr->opc);
error();
+
+
+
} /* switch */
+
} /* for instruction */
-
+
/* copy values to interface registers */
src = bptr->outstack;
} /* if (bptr -> flags >= BBREACHED) */
} /* for basic block */
- bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
+ /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
{
/* generate bound check stubs */
continue;
}
+
gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
THREAD_OBJ = @THREAD_OBJ@
VERSION = @VERSION@
-EXTRA_DIST = block.c local.c parse.c reg.c stack.c var.c defines.c mcode.c pcmd.c regalloc.c tools.c
-
+EXTRA_DIST = block.c local.c parse.c reg.c stack.c var.c \
+ defines.c mcode.c pcmd.c regalloc.c tools.c
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
-all: all-redirect
+GZIP = --best
+all: Makefile
+
.SUFFIXES:
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps comp/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu comp/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
subdir = comp
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu comp/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile
-all-redirect: all-am
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-generic
-
-mostlyclean: mostlyclean-am
-
-clean-am: clean-generic mostlyclean-am
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-generic
-clean: clean-am
+clean: clean-generic mostlyclean
-distclean-am: distclean-generic clean-am
+distclean: distclean-generic clean
+ -rm -f config.status
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-generic distclean-am
+maintainer-clean: maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
-.PHONY: tags distdir info-am info dvi-am dvi check check-am \
-installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+.PHONY: tags distdir info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
#undef EXTERNAL_OVERFLOW
#undef DONT_FREE_FIRST
+/* Make automake happy */
+#undef PACKAGE
+#undef VERSION
+
/* sysdep */
#undef SYSDEP_DIR
/* Define if you have the m library (-lm). */
#undef HAVE_LIBM
-
-/* Name of package */
-#undef PACKAGE
-
-/* Version number of package */
-#undef VERSION
-
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
+# Generated automatically using autoconf version 2.12
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12
verbose=yes ;;
-version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
+ echo "configure generated by autoconf version 2.12"
exit 0 ;;
-with-* | --with-*)
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
-ac_exeext=
-ac_objext=o
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
# Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
# Make sure we can run config.sub.
-if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:556: checking host system type" >&5
+echo "configure:553: checking host system type" >&5
host_alias=$host
case "$host_alias" in
NONE)
case $nonopt in
NONE)
- if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ if host_alias=`$ac_config_guess`; then :
else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
fi ;;
*) host_alias=$nonopt ;;
esac ;;
esac
-host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host=`$ac_config_sub $host_alias`
host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:589: checking for a BSD compatible install" >&5
+echo "configure:585: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
for ac_dir in $PATH; do
# Account for people who put trailing slashes in PATH elements.
case "$ac_dir/" in
/|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
+ for ac_prog in ginstall installbsd scoinst install; do
if test -f $ac_dir/$ac_prog; then
if test $ac_prog = install &&
grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
:
else
ac_cv_path_install="$ac_dir/$ac_prog -c"
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
-
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
-echo "configure:642: checking whether build environment is sane" >&5
+echo "configure:638: checking whether build environment is sane" >&5
# Just in case
sleep 1
echo timestamp > conftestfile
test "$program_transform_name" = "" && program_transform_name="s,x,x,"
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:699: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:695: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
missing_dir=`cd $ac_aux_dir && pwd`
echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
-echo "configure:745: checking for working aclocal" >&5
+echo "configure:741: checking for working aclocal" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
fi
echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
-echo "configure:758: checking for working autoconf" >&5
+echo "configure:754: checking for working autoconf" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
fi
echo $ac_n "checking for working automake""... $ac_c" 1>&6
-echo "configure:771: checking for working automake" >&5
+echo "configure:767: checking for working automake" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
fi
echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
-echo "configure:784: checking for working autoheader" >&5
+echo "configure:780: checking for working autoheader" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
fi
echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
-echo "configure:797: checking for working makeinfo" >&5
+echo "configure:793: checking for working makeinfo" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:854: checking for $ac_word" >&5
+echo "configure:850: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_CC="gcc"
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:884: checking for $ac_word" >&5
+echo "configure:879: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
ac_prog_rejected=no
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
+ for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
echo "$ac_t""no" 1>&6
fi
- if test -z "$CC"; then
- case "`uname -s`" in
- *win32* | *WIN32*)
- # Extract the first word of "cl", so it can be a program name with args.
-set dummy cl; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:935: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="cl"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
- ;;
- esac
- fi
test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:967: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:927: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
-cat > conftest.$ac_ext << EOF
-
-#line 978 "configure"
+cat > conftest.$ac_ext <<EOF
+#line 937 "configure"
#include "confdefs.h"
-
main(){return(0);}
EOF
-if { (eval echo configure:983: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:941: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
ac_cv_prog_cc_works=no
fi
rm -fr conftest*
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:1009: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:961: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:1014: checking whether we are using GNU C" >&5
+echo "configure:966: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1023: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:975: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
if test $ac_cv_prog_gcc = yes; then
GCC=yes
-else
- GCC=
-fi
-
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-CFLAGS=
-echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1042: checking whether ${CC-cc} accepts -g" >&5
+ ac_test_CFLAGS="${CFLAGS+set}"
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:990: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
+ if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+ elif test $ac_cv_prog_cc_g = yes; then
CFLAGS="-g -O2"
else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
CFLAGS="-O2"
- else
- CFLAGS=
fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
fi
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1076: checking for $ac_word" >&5
+echo "configure:1020: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_RANLIB="ranlib"
echo $ac_n "checking for sin in -lm""... $ac_c" 1>&6
-echo "configure:1105: checking for sin in -lm" >&5
+echo "configure:1048: checking for sin in -lm" >&5
ac_lib_var=`echo m'_'sin | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1113 "configure"
+#line 1056 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
sin()
; return 0; }
EOF
-if { (eval echo configure:1124: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1067: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:1157: checking for $ac_hdr that defines DIR" >&5
+echo "configure:1100: checking for $ac_hdr that defines DIR" >&5
if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1162 "configure"
+#line 1105 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
DIR *dirp = 0;
; return 0; }
EOF
-if { (eval echo configure:1170: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1113: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=yes"
else
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:1195: checking for opendir in -ldir" >&5
+echo "configure:1138: checking for opendir in -ldir" >&5
ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1203 "configure"
+#line 1146 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
opendir()
; return 0; }
EOF
-if { (eval echo configure:1214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
else
echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:1236: checking for opendir in -lx" >&5
+echo "configure:1179: checking for opendir in -lx" >&5
ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1244 "configure"
+#line 1187 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
opendir()
; return 0; }
EOF
-if { (eval echo configure:1255: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1198: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1278: checking how to run the C preprocessor" >&5
+echo "configure:1221: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 1293 "configure"
+#line 1236 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1299: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+{ (eval echo configure:1242: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 1310 "configure"
+#line 1253 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1316: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -nologo -E"
- cat > conftest.$ac_ext <<EOF
-#line 1327 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1333: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+{ (eval echo configure:1259: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
else
fi
rm -f conftest*
fi
-rm -f conftest*
-fi
rm -f conftest*
ac_cv_prog_CPP="$CPP"
fi
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1358: checking for ANSI C header files" >&5
+echo "configure:1282: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1363 "configure"
+#line 1287 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1371: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+{ (eval echo configure:1295: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
ac_cv_header_stdc=yes
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1388 "configure"
+#line 1312 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1406 "configure"
+#line 1330 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
:
else
cat > conftest.$ac_ext <<EOF
-#line 1427 "configure"
+#line 1351 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
exit (0); }
EOF
-if { (eval echo configure:1438: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1362: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
:
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1465: checking for $ac_hdr" >&5
+echo "configure:1389: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1470 "configure"
+#line 1394 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1475: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+{ (eval echo configure:1399: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
eval "ac_cv_header_$ac_safe=yes"
echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1503: checking for working const" >&5
+echo "configure:1427: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1508 "configure"
+#line 1432 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:1557: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1481: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
fi
echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:1578: checking for inline" >&5
+echo "configure:1502: checking for inline" >&5
if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat > conftest.$ac_ext <<EOF
-#line 1585 "configure"
+#line 1509 "configure"
#include "confdefs.h"
int main() {
} $ac_kw foo() {
; return 0; }
EOF
-if { (eval echo configure:1592: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1516: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_inline=$ac_kw; break
else
esac
echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:1618: checking for off_t" >&5
+echo "configure:1542: checking for off_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1623 "configure"
+#line 1547 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
rm -rf conftest*
ac_cv_type_off_t=yes
else
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:1651: checking for size_t" >&5
+echo "configure:1575: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1656 "configure"
+#line 1580 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
rm -rf conftest*
ac_cv_type_size_t=yes
else
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:1684: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:1608: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1689 "configure"
+#line 1613 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
struct tm *tp;
; return 0; }
EOF
-if { (eval echo configure:1698: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1622: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
fi
echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
-echo "configure:1719: checking whether struct tm is in sys/time.h or time.h" >&5
+echo "configure:1643: checking whether struct tm is in sys/time.h or time.h" >&5
if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1724 "configure"
+#line 1648 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <time.h>
struct tm *tp; tp->tm_sec;
; return 0; }
EOF
-if { (eval echo configure:1732: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1656: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_tm=time.h
else
if test $ac_cv_prog_gcc = yes; then
echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:1755: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:1679: checking whether ${CC-cc} needs -traditional" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_pattern="Autoconf.*'x'"
cat > conftest.$ac_ext <<EOF
-#line 1761 "configure"
+#line 1685 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
if test $ac_cv_prog_gcc_traditional = no; then
cat > conftest.$ac_ext <<EOF
-#line 1779 "configure"
+#line 1703 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
fi
echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:1801: checking for 8-bit clean memcmp" >&5
+echo "configure:1725: checking for 8-bit clean memcmp" >&5
if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_func_memcmp_clean=no
else
cat > conftest.$ac_ext <<EOF
-#line 1809 "configure"
+#line 1733 "configure"
#include "confdefs.h"
main()
}
EOF
-if { (eval echo configure:1819: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1743: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
ac_cv_func_memcmp_clean=yes
else
fi
echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
-test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
+test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.o"
for ac_hdr in unistd.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1840: checking for $ac_hdr" >&5
+echo "configure:1764: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1845 "configure"
+#line 1769 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1850: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+{ (eval echo configure:1774: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
eval "ac_cv_header_$ac_safe=yes"
for ac_func in getpagesize
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1879: checking for $ac_func" >&5
+echo "configure:1803: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1884 "configure"
+#line 1808 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:1907: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
done
echo $ac_n "checking for working mmap""... $ac_c" 1>&6
-echo "configure:1932: checking for working mmap" >&5
+echo "configure:1856: checking for working mmap" >&5
if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_func_mmap_fixed_mapped=no
else
cat > conftest.$ac_ext <<EOF
-#line 1940 "configure"
+#line 1864 "configure"
#include "confdefs.h"
/* Thanks to Mike Haertel and Jim Avera for this test.
}
EOF
-if { (eval echo configure:2080: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2004: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
ac_cv_func_mmap_fixed_mapped=yes
else
fi
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:2103: checking return type of signal handlers" >&5
+echo "configure:2027: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2108 "configure"
+#line 2032 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
int i;
; return 0; }
EOF
-if { (eval echo configure:2125: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2049: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
for ac_func in getcwd gettimeofday mkdir mktime select socket
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2146: checking for $ac_func" >&5
+echo "configure:2070: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2151 "configure"
+#line 2075 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:2174: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2098: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
if test $ac_cv_func_mmap_fixed_mapped = yes; then
echo $ac_n "checking whether MAP_FAILED is defined""... $ac_c" 1>&6
-echo "configure:2201: checking whether MAP_FAILED is defined" >&5
+echo "configure:2125: checking whether MAP_FAILED is defined" >&5
if eval "test \"`echo '$''{'ac_cv_map_failed'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2206 "configure"
+#line 2130 "configure"
#include "confdefs.h"
#include <sys/mman.h>
#ifdef MAP_FAILED
echo "$ac_t""$ac_cv_map_failed" 1>&6
echo $ac_n "checking whether MAP_ANONYMOUS is defined""... $ac_c" 1>&6
-echo "configure:2228: checking whether MAP_ANONYMOUS is defined" >&5
+echo "configure:2152: checking whether MAP_ANONYMOUS is defined" >&5
if eval "test \"`echo '$''{'ac_cv_map_anonymous'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2233 "configure"
+#line 2157 "configure"
#include "confdefs.h"
#include <sys/mman.h>
#ifdef MAP_ANONYMOUS
echo $ac_n "checking whether to include threads support""... $ac_c" 1>&6
-echo "configure:2285: checking whether to include threads support" >&5
+echo "configure:2209: checking whether to include threads support" >&5
if test x"$enable_threads" = "xno"; then
echo "$ac_t""no" 1>&6
else
fi
echo $ac_n "checking which garbage collector to use""... $ac_c" 1>&6
-echo "configure:2311: checking which garbage collector to use" >&5
+echo "configure:2235: checking which garbage collector to use" >&5
if test x"$enable_gc2" = "xno"; then
echo "$ac_t""old garbage collector" 1>&6
GC_OBJ="mm/libmm_old.a"
# 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
+ case `(ac_space=' '; set) 2>&1` in
*ac_space=\ *)
# `set' does not quote correctly, so add quotes (double-quote substitution
# turns \\\\ into \\, and sed turns \\ into \).
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ echo "$CONFIG_STATUS generated by autoconf version 2.12"
exit 0 ;;
-help | --help | --hel | --he | --h)
echo "\$ac_cs_usage"; exit 0 ;;
alpha/Makefile \
mips/Makefile \
nat/Makefile \
+ doc/Makefile \
comp/Makefile \
- doc/Makefile \
+ narray/Makefile \
tst/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub
-s%@SHELL@%$SHELL%g
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@host_vendor@%$host_vendor%g
s%@host_os@%$host_os%g
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
s%@PACKAGE@%$PACKAGE%g
s%@VERSION@%$VERSION%g
s%@ACLOCAL@%$ACLOCAL%g
alpha/Makefile \
mips/Makefile \
nat/Makefile \
+ doc/Makefile \
comp/Makefile \
- doc/Makefile \
+ narray/Makefile \
tst/Makefile "}
EOF
cat >> $CONFIG_STATUS <<\EOF
--- /dev/null
+\documentclass[12pt]{article}
+
+\begin{document}
+
+\title{Array Bound-Check Removal}
+\author{Kruegel Christopher\\TU Vienna\\cacao@complang.tuwien.ac.at}
+\maketitle
+
+\section{Introduction}
+
+In safe programming languages like Java, all array accesses are
+checked. It is assured that the used index is greater or equal to
+zero and less than the array length, otherwise an
+ArrayIndexOutOfBoundsException is thrown. It is obvious that this
+gain in saftey causes a run-time overhead that is especially
+unpleasant in loops where these checks have to be performed many
+times. Often it is possible to remove these checks in loops by
+inserting additional tests at the beginning of the loop and
+examinig the code structure and loop condition thereby saving run-
+time speed at each loop execuion. The following algorithm performs
+this task for a special set of array accesses in loops. It should
+be obvious that it is not always possible to predict the value of
+an array index by inserting tests at the beginning of the loop. An
+example would be a global variable that is used as an array index.
+This variable could be changed by a different thread virtually any
+time, so removing a bound check for this array access is not a
+good idea. The following algorithm only performs bound check
+removal, when the induction variable (the variable used as array
+index) is local and is only modified by adding/subtracting a
+constant inside the loop body or remains unchanged (is constant).
+If a constant is used as index, optimzation can take place as
+well. When other variables are used to modify the induction
+variable or when different arithmetic operations are used, no
+optimization can take place. Nevertheless, the most common use for
+index variables in loops is their increment or decrement by a
+constant, so most of the array access should be considered for
+optimization.
+
+\section{Initialization}
+
+Before array bound checks in loops can be eliminated, the loops
+have to be detected. The algorithm performs its analysis on
+intermediate code level, so we cannot rely on just looking at
+while/for statments. A basic block analysis has been completed, so
+the algorithm can work on this data structure already. It uses the
+Lengauer-Tarjan algorithm to find existing loops, which bases on
+determining the dominator tree (a reference with extensive
+documentation for this algorithm can be found in \cite{tig}). It uses a
+depth first search on the control flow graph to build a spanning
+tree. Then the semidominator and dominator theorem are utilized to
+extract the dominator tree and by looking at back edges (a back
+edge is an edge where the target node dominates the source node)
+all loops can be detected. Before starting to look at each loop,
+the case of different loops that share the same header node has to
+be considered. The algorithm works on each loop not looking on any
+other loop and performs its optimzation. The procedures that
+analyze the control flow of the program, build a flow graph and
+extract the loops can be found in the files graph.c (for control
+flow graph) and loop.c (for the loop extractig algorithm). The
+control flow graph is simple built by looking at the last
+instruction of each basic block and then deciding, which other
+blocks can be reached by that instruction. One problem can occur,
+when lookup/table-switch instructions cause multiple jumps to the
+same node. It must be prevented that the target node´s predecessor
+list contains that node more than once. So an additionally array
+is needed to prevent double entries in the predecessor array. When
+the necessary flow data structure and the list of all loops has
+been built, the main algorithm can start.
+
+
+\section{Algorithm}
+
+The procedures for the main algorithm can be found in analyze.c.
+Before each loops is processed on its own, two global
+preprocessing steps are necessary.
+
+The first step deals with loops, that share the same header node.
+This special case can happen when a loop body ends with an if-
+then/else statment. The loop finding algorithm then reports two
+different loops, which share the same header node. When additional
+tests are inserted at the header node and another loop sharing the
+same header is later evaluated, inserting different tests,
+problems could arise. To prevent this from happening, loops
+sharing the same header node are simply merged into a bigger one
+by unioning their nodes. Because the nodes of the loop are already
+sorted by increasing basic block numbers, a simple merge of the
+nodes can be done (analyze\_double\_headers).
+
+The second step before the loop by loop analysis commences is the
+building of a loop hierarchie. Nested loops cause problems when
+variables that are used as array indexes elsewhere get modified.
+Because these modifications (eg. an increment by a constant) can
+happen an unknown number of times, their results are
+unpredictable. These modifications in nested loops have to be
+recognized and reacted upon accordingly. The algorithm builds a
+tree where each node represents a loop with its parent being the
+directly surrounding loop. A dummy root node, representing the
+whole function has to be inserted as well. When loops have to be
+duplicated because of optimzed array accesses, it is important to
+extend or duplicate exception entries as well. Because of that,
+exceptions are inserted into the tree as follows. Every exception
+is inserted at the node in the hierarchie that represents the
+loop, that directly contains this exception. When an exception is
+part of a nested loop, it is inserted only at the node,
+representing this nested loop, because by following this nodes
+parent pointers, we find all other loops, that contain the
+exception (analyze\_nested). Finally, the sequentiel order of the
+loops is determined by a topological sort of the loops, satisfying
+the condition, that all nested loops have to be optimzed before
+their parent loop is processed. This can be archieved by a post-
+order traversal of the hierarchie tree with skipping the root
+node.
+
+After these global steps have been completed, each loop is
+processed. Then the loops are checked for array accesses
+(analyze\_for\_array\_access) and the process exits if none
+are found. Finally, two special cases must be considered.
+
+\begin{enumerate}
+
+\item The algorithm uses the loop condition to guarantee certain
+bounds for variables. If the loop condition consists of an or-
+statement, these guarantees can not be held up. If the loop
+statement reads
+
+\begin{verbatim}
+while ((var > 0) or true)
+\end{verbatim}
+
+vars value is not bound to be greater than zero. When an or-statement
+is found, loop optimization is stopped.
+
+\item Variables that are used as indexes in array accesses might be
+modified in exception handling code of try-catch statements inside
+the loop. Because code in catch blocks is not considered in the
+control flow graph and because these modifications happen
+unpredictable (and should occur rarely) loops containing these
+catch blocks with index variable modifications are not optimized.
+During the scan for array accesses within the loop, all
+interesting variables are recorded. A variable is considered
+interesting, when it is used as index in an array access or when
+its value is changes (due to a store instruction)
+(analyze\_or\_exceptions and scan\_global\_list).
+
+\end{enumerate}
+
+The next step is responsible for the analyzation of the loop
+condition itself. The loop condition can create a so called
+dynamic constraint on a variable. If one side of the loop
+condition is constant during the execution of the loop the other
+side can be safely assumed to be less than, greater or equal
+than or equal to this side (depending on the operator) at the
+start of each loop pass. It is important to notice the difference
+to so called static constraints on variables. That means that
+these variables can be safely assumed to stay below or above a
+certain constant during the loop execution by simple testing them
+prior to loop entry. This is obviously true for constants but does
+also hold for variables that are only decremented or incremented.
+For these, a static lower or upper bound can be guaranteed for the
+whole loop execution by simply inserting a single test prior to
+loop entry. Dynamic constraints, on the contrary, can vary in
+different parts of the loop. After the variable is tested in the
+loop condition, it might be changed to different values in
+different paths of execution. All variables, that are never
+changed or that get only decremented/incremented have static and
+dynamic constraints, all others can only have dynamic ones
+(init\_constraint).
+
+Now the core bound check removal procedure is started. Beginning
+directly after the loop condition all changes of variables that
+are used as index variables somewhere in the loop are recorded.
+This is an iterative process since different paths of execution
+may yield different changes to these variables. Especially changes
+in nested loops cause these changes to become unpredictable and
+therefore no upper/lower bound can be held up any further. After
+this iterative process caused all changes to become stable, each
+array access is examined (e.g. a statement like
+\newpage
+\begin{verbatim}
+if (x == true)
+ i++;
+else
+ i+=2;
+\end{verbatim}
+must result in an increase of 2 for i when control
+flow joins after the if-statement). If it is possible, by
+inserting additional static/dynamic tests as needed, to assure
+that the index variable is greater or equal to zero and less than
+the array length, the bound checks are removed
+(remove\_bound\_checks). It is possible that more than one static
+tests gets inserted for a single variable, when it is used in
+different array access (possibly with different constants added or
+subtracted). Because all tests have to hold for this variable to
+allow optimzed code to be executed, only the strictest tests have
+to be done (e.g. if an integer array x[] is accessed by i in the
+statements x[i+1] and x[i-1], it has to be guaranteed that i $>$ 1
+(for second statement) and that i $<$ arraylength-1 (for the first
+statement)). Parallel to the insertion of new tests, the number of
+needed instructions for the new loop header node is accordingly
+increased. When optimzing the loop, it is important to
+differentiate between the loop head and the rest of the basic
+blocks, forming the body. The dynamic constraints can only be used
+for array accesses in the loop body, as the loop comparison is
+done at the end of the header node. Nevertheless, all static
+constraints can still be used to optimze array access in the
+header block. Because it is possible that an array reference is
+null prior to entering the loop, all array references that are
+loaded to compute an arraylength have to be checked against null.
+
+After all new tests have been determined, it is necessary to
+reorder the code and insert the new tests (insert\_static\_checks).
+The first step is the creation of a new header node. Because all
+jumps to the beginning of the old loop now have to get to the new
+header first, it is more efficient to just replace the code in the
+old header block by the new tests. So only jumps within the loops
+need to be patched and the rest of the code can remain untouched.
+For each constraint that has been found in the previous step of
+the algorithm, two values have to be loaded and are then compared.
+Because it is possible during runtime that these tests fail (and
+no guarantee can be made) a copy of the loop with the original,
+checked array accesses must exist. Depending on the outcome of the
+test cascade, a jump to the optimized or original loop is made. To
+copy the loop, all basic blocks that are part of the loop are
+copied and appended to the end of the global basic block list.
+After that, both the original and the copy of the loop need post-
+processing to redirect certain jump targets. All jumps to the old
+loop head (which now contains the static checks) in the original
+loop have to be redirected to the newly inserted block, that holds
+the code for the original loop head. In the copied loop, all jumps
+inside the loop have to be redirected to jumps to the copied
+blocks. When loops are duplicated, these changes must be reflected
+in the node list of all parent loops as well. So the hierarchie
+tree is climbed and the new nodes are added to all enclosing
+loops. Because these node lists are sorted, it is necessary to
+deal with the new loop head in a different way. The loop head has
+to be inserted into the correct place of the parent loops while
+all other copied nodes can simply be appended to the basic block
+list.
+
+Now all exceptions have to be examined. There are three different
+cases, that must be considered. An exception can be part of the
+loop body (ie. is inside the loop), an exception can contain the
+loop or an exception is in a different part of the code (and does
+not have to be further considered). To be able to find all
+exceptions that are part of the loop, the algorithm uses the
+hierarchie tree and gets all exceptions of all children nodes. The
+exception handlers of these loops have to be copied and jumps to
+the original loop have to be redirected to the copied loop. The
+start and end code pointers of the protected area have to be moved
+to the copied blocks. The exception handler code is identified by
+looking at the successor nodes starting from the handler block. As
+long as control flow does not reach a loop node again, all blocks
+are considered as part of the handler code. Exceptions that
+surround the loop have to be handled different. It is not
+necessary to copy the exception handler, as it is not part of the
+loop. Nevertheless it is important to extend the protected area to
+the copied blocks. So the first and last block (including copied
+exception handler blocks of nested loops) that got copied are
+stored. The exceptions are then extended to contain all these new
+blocks and jump to the original handler. As no code is duplicated,
+nothing needs to be patched. When climbing up the hierarchie tree
+by following the parent pointer, not all exceptions of parent
+nodes really enclose the loop. It is possible that a parent loop
+contains an exception and the loop, that is optimized, right after
+each other. Those exceptions must not be handled and are ignored.
+Because of the layout of the exception table, where appropriate
+exceptions (that could be nested) are found by a linear search
+from the start, it is necessary to insert newly created exceptions
+right after their original ones.
+
+One performance problem still remains after these modifications.
+The new loop header that replaces the original one is located
+exactly where the old one was. A fall through from the previous
+block (that could be part of the loop) to the loop header must be
+patched by inserting an additional goto-instruction to the
+original head of the loop. Because this would insert an additional
+jump into the loop body, performance may deteriorate. To solve
+this shortcoming, the new loop head has to be moved before the
+first node of the loop. This might cause the problem of moving the
+loop head to the beginning of the global basic block list. This
+pointer points to the initial basic block array and can not be
+easily reassigned. A new pointer is needed that temporary holds
+the begin of the basic block list and is assigned to the original
+pointer after all optimization step have been finished. Any fall
+through from the predecessor of the loop head now reaches the old
+loop head, that has been inserted right after the new loop head.
+After all loops have been processed, register allocation and code
+genration proceed as usual and optimized code is generated.
+
+\section{Helper functions}
+
+An important helper function is stored in tracing.c. This
+functions is needed to determine the variables/constants that
+participate in array accesses or comparisons. As all work is done
+on java bytecode, it is necessary to find the arguments of an
+interesting operation by examining the stack. Unfortunately these
+values can just be temporary and origin in variables loaded
+earlier and getting modified by arithmetic operations. To find the
+variables that participate in an array access, one has to walk
+back instructions and looking at the stack, until an appropriate
+load is found. The function tracing preforms this task by steping
+back instruction for instruction and record the stack changes
+these instructions cause until the correct load or push constant
+operating has been found or until it becomes clear, that it is
+impossible to determine the origin (e.g. when a function return
+value is used). The value is then delivered in a special structure
+and used by the main algorithm.
+
+\section{Performance - impact and gain}
+
+It is obvious that the optimization process causes additionally
+compile time overhead but can give performance gains during
+runtime, when 3 less instructions are executed per array access
+many times in a loop. The additional overhaed is mainly caused by
+the needed control flow analysis, which has to be done for every
+method and is linear to the number of basic blocks. Then the loop
+scaning algorithm trys to find loops in the control flow graph.
+This algorithm has to be started every time a method is compiled
+and runs in O(n*ld(n)) where n is the number of basic blocks.
+After the loops have been scanned for array access, the runtime of
+the final bound check removal and loop copying process mainly
+depends on the nesting depth of the hierarchie tree. For every
+additional nesting depth, the number of basic blocks, that must be
+copied and patch is doubled, resulting in exponential overhead
+according to the nesting depth. Additionally, the search for
+modifications of index variables, which is an iterative process,
+becomes slowed down by deeply nested loops. Things get worse when
+many exceptions are involved, because not only exceptions in
+children nodes have to be considered, but all enclosing exceptions
+as well. Nevertheless those cases should rarely occur and in real
+environments, the net gain can be significant. Especially in tight
+loops, when arrays are initialized or their elements summed up,
+three less instructions can gain up to 30 percent speedup, when loops run
+many times.
+
+
+\subsection{Tables}
+
+\vspace{4mm}
+
+\begin{tabular}{|l|c|c|c|}
+
+\hline
+
+& Compile time (in ms) & \multicolumn{2}{c|}{Run time (in ms) } \\
+
+\multicolumn{1}{|c|}{\raisebox{1ex}{Cacao Options}} & javac & perf & sieve 1000 1000\\ \hline
+
+\rule{0mm}{5mm}with optimization (-oloop) & 176 & 1510 & 98 \\
+
+without optimization & 118 & 1720 & 131 \\
+
+\hline
+
+\end{tabular}
+
+
+\begin{thebibliography}{9}
+
+\bibitem{tig} A. Appel; modern compiler implementation in C; Cambridge University Press; 1998
+
+\bibitem{aho} A. Aho, R.Sethi, J. Ullman; Compilers - Principles,
+Techniques, and Tools; Addison-Wesly; 1986
+
+\end{thebibliography}
+
+\end{document}
+
+
+
+
+
+
+
+
Changes: Mark Probst (schani) EMAIL: cacao@complang.tuwien.ac.at
Philipp Tomsich (phil) EMAIL: cacao@complang.tuwien.ac.at
- Last Change: $Id: global.h 118 1999-01-20 14:58:16Z andi $
+ Last Change: $Id: global.h 132 1999-09-27 15:54:42Z chris $
*******************************************************************************/
} fieldinfo;
+struct basicblock;
/* exceptiontable *************************************************************/
+typedef struct xtable { /* exceptiontable entry in a method */
+ s4 startpc; /* start pc of guarded area (inclusive) */
+ struct basicblock *start;
+
+ s4 endpc; /* end pc of guarded area (exklusive) */
+ struct basicblock *end;
+
+ s4 handlerpc; /* pc of exception handler */
+ struct basicblock *handler;
+
+ classinfo *catchtype; /* catchtype of exception (NULL == catchall) */
+ struct xtable *next; /* used to build a list of exception when */
+ /* loops are copied */
+ struct xtable *down; /* instead of the old array, a list is used */
+} xtable;
+
+
typedef struct exceptiontable { /* exceptiontable entry in a method */
s4 startpc; /* start pc of guarded area (inclusive) */
s4 endpc; /* end pc of guarded area (exklusive) */
u1 *jcode; /* pointer to JavaVM code */
s4 exceptiontablelength;/* exceptiontable length */
- exceptiontable *exceptiontable; /* the exceptiontable */
+ exceptiontable *exceptiontable;
+ /* the exceptiontable */
u1 *stubroutine; /* stub for compiling or calling natives */
s4 mcodelength; /* legth of generated machine code */
#include "threads/thread.h"
+/* include compiler data types ************************************************/
+
+#include "jit/jitdef.h"
+#include "narray/loop.h"
+
/* global switches ************************************************************/
+int num_compiled_m = 0;
+int myCount;
bool compileverbose = false;
bool showstack = false;
bool checknull = true;
bool checkfloats = true;
bool checksync = true;
+bool opt_loops = false;
bool getcompilingtime = false;
long compilingtime = 0;
int *count_store_depth = count_store_depth_init;
-/* include compiler data types ************************************************/
-
-#include "jit/jitdef.h"
-
/* global compiler variables **************************************************/
static int jcodelength; /* length of JavaVM-codes */
static u1 *jcode; /* pointer to start of JavaVM-code */
static int exceptiontablelength;/* length of exception table */
-static exceptiontable *extable; /* pointer to start of exception table */
+static xtable *extable; /* pointer to start of exception table */
+static exceptiontable *raw_extable;
static int block_count; /* number of basic blocks */
static basicblock *block; /* points to basic block array */
static bool isleafmethod; /* true if a method doesn't call subroutines */
+static basicblock *last_block; /* points to the end of the BB list */
+
/* list of all classes used by the compiled method which have to be */
/* initialised (if not already done) before execution of this method */
#include "jit/parse.c" /* parsing of JavaVM code */
#include "jit/reg.c" /* register allocation and support routines */
#include "jit/stack.c" /* analysing the stack operations */
-#include "ngen.c" /* code generator */
-
-
+#include "sysdep/ngen.c" /* code generator */
+#include "narray/graph.c" /* array bound removal */
+#include "narray/loop.c" /* array bound removal */
+#include "narray/tracing.c" /* array bound removal */
+#include "narray/analyze.c" /* array bound removal */
/* dummy function, used when there is no JavaVM code available */
methodptr jit_compile(methodinfo *m)
{
- int dumpsize;
+ int dumpsize, i, j, k;
long starttime = 0;
long stoptime = 0;
+ basicblock *b;
+ instruction *ip;
+ stackptr sp;
+
+ basicblock *bptr;
+ stackptr sptr;
+ int cnt;
+
+
#ifdef OLD_COMPILER
if (!newcompiler) {
jcodelength = m->jcodelength;
jcode = m->jcode;
exceptiontablelength = m->exceptiontablelength;
- extable = m->exceptiontable;
+ raw_extable = m->exceptiontable;
#ifdef STATISTICS
count_tryblocks += exceptiontablelength;
/* call the compiler passes ***********************************************/
reg_init();
+
local_init();
+
mcode_init();
parse();
analyse_stack();
+
+ if (opt_loops) {
+ depthFirst();
+#ifdef LOOP_DEBUG
+ resultPass1();
+ fflush(stdout);
+#endif
+ analyseGraph();
+#ifdef LOOP_DEBUG
+ resultPass2();
+ fflush(stdout);
+#endif
+ optimize_loops();
+#ifdef LOOP_DEBUG
+ /* resultPass3(); */
+#endif
+ }
+
+#ifdef LOOP_DEBUG
+ printf("Allocating registers ");
+ fflush(stdout);
+#endif
interface_regalloc();
-
+#ifdef LOOP_DEBUG
+ printf(".");
+ fflush(stdout);
+#endif
allocate_scratch_registers();
-
+#ifdef LOOP_DEBUG
+ printf(".");
+ fflush(stdout);
+#endif
local_regalloc();
-
+#ifdef LOOP_DEBUG
+ printf(". done\n");
+
+ printf("Generating MCode ... ");
+ fflush(stdout);
+#endif
gen_mcode();
+#ifdef LOOP_DEBUG
+ printf("done\n");
+ fflush(stdout);
+#endif
-
/* intermediate and assembly code listings ********************************/
if (showintermediate)
if (showddatasegment)
dseg_display((void*) (m->mcode));
-
-
/* release dump area */
dump_release (dumpsize);
/* return pointer to the methods entry point */
return m -> entrypoint;
-}
-
+}
/* functions for compiler initialisation and finalisation *********************/
extern int optimizelevel; /* optimzation level (0 = no optimization) */
extern bool checkbounds; /* check array bounds */
+extern bool opt_loops; /* optimize array accesses in loops */
extern bool checknull; /* check null pointers */
extern bool checkfloats; /* implement ieee compliant floats */
extern bool checksync; /* do synchronization */
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
-all: all-redirect
+GZIP = --best
+all: Makefile
+
.SUFFIXES:
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps jit/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu jit/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
subdir = jit
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu jit/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile
-all-redirect: all-am
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-generic
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-generic
-mostlyclean: mostlyclean-am
+clean: clean-generic mostlyclean
-clean-am: clean-generic mostlyclean-am
+distclean: distclean-generic clean
+ -rm -f config.status
-clean: clean-am
-
-distclean-am: distclean-generic clean-am
-
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-generic distclean-am
+maintainer-clean: maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
-.PHONY: tags distdir info-am info dvi-am dvi check check-am \
-installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+.PHONY: tags distdir info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
double d; /* double operand */
void *a; /* address operand */
} val; /* immediate constant */
+
+ void *target; /* used for targets of branches and jumps */
+ /* and as address for list of targets for */
+ /* statements */
};
int outdepth; /* stack depth end of basic block */
int pre_count; /* count of predecessor basic blocks */
branchref *branchrefs; /* list of branches to be patched */
+
+ basicblock *next; /* used to build a BB list (instead of array) */
+ int lflags; /* used during loop copying, init with 0 */
+ basicblock *copied_to; /* points to the copy of this basic block */
+ /* when loop nodes are copied */
+
+ int debug_nr;
+
};
jr = jumpreferences;
while (jr != NULL) {
- *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
- jr = jr->next;
- }
+ *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
+ jr = jr->next;
+ }
}
Author: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
- Last Change: $Id: parse.c 115 1999-01-20 01:52:45Z phil $
+ Last Change: $Id: parse.c 132 1999-09-27 15:54:42Z chris $
*******************************************************************************/
/* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
/* additional MONITOREXITS are reached by branches which are 3 bytes */
- iptr = instr = DMNEW(instruction, jcodelength + 5);
+ iptr = instr = DMNEW(instruction, jcodelength + 5);
/* initialize block_index table (unrolled four times) */
/* compute branch targets of exception table */
+ extable = DMNEW(xtable, exceptiontablelength + 1);
+
for (i = 0; i < exceptiontablelength; i++) {
- p = extable[i].startpc;
+
+ p = extable[i].startpc = raw_extable[i].startpc;
bound_check(p);
block_insert(p);
- p = extable[i].endpc;
+
+ p = extable[i].endpc = raw_extable[i].endpc;
bound_check1(p);
if (p < jcodelength)
block_insert(p);
- p = extable[i].handlerpc;
+
+ p = extable[i].handlerpc = raw_extable[i].handlerpc;
bound_check(p);
block_insert(p);
+
+ extable[i].catchtype = raw_extable[i].catchtype;
+
+ extable[i].next = NULL;
+ extable[i].down = &extable[i+1];
}
+ if (exceptiontablelength > 0)
+ extable[exceptiontablelength-1].down = NULL;
+ else
+ extable = NULL;
+
s_count = 1 + exceptiontablelength; /* initialize stack element counter */
#ifdef USE_THREADS
bptr = block = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
b_count = 0;
+ c_debug_nr = 0;
/* additional block if target 0 is not first intermediate instruction */
bptr->type = BBTYPE_STD;
bptr->branchrefs = NULL;
bptr->pre_count = 0;
+ bptr->debug_nr = c_debug_nr++;
bptr++;
b_count++;
+ (bptr - 1)->next = bptr;
+
}
/* allocate blocks */
+
for (p = 0; p < jcodelength; p++)
+
if (block_index[p] & 1) {
bptr->iinstr = instr + (block_index[p] >> 1);
+ bptr->debug_nr = c_debug_nr++;
if (b_count != 0)
(bptr - 1)->icount = bptr->iinstr - (bptr - 1)->iinstr;
bptr->mpc = -1;
bptr->flags = -1;
+ bptr->lflags = 0;
bptr->type = BBTYPE_STD;
bptr->branchrefs = NULL;
block_index[p] = b_count;
bptr->pre_count = 0;
bptr++;
b_count++;
+
+ (bptr - 1)->next = bptr;
}
/* allocate additional block at end */
+
+ bptr->instack = bptr->outstack = NULL;
+ bptr->indepth = bptr->outdepth = 0;
bptr->iinstr = NULL;
(bptr - 1)->icount = (instr + instr_count) - (bptr - 1)->iinstr;
bptr->icount = 0;
bptr->mpc = -1;
bptr->flags = -1;
+ bptr->lflags = 0;
bptr->type = BBTYPE_STD;
bptr->branchrefs = NULL;
bptr->pre_count = 0;
+ bptr->debug_nr = c_debug_nr++;
+
+ (bptr - 1)->next = bptr;
+ bptr->next = NULL;
+
+ last_block = bptr;
+
+
+
+ for (i = 0; i < exceptiontablelength; ++i) {
+ p = extable[i].startpc;
+ extable[i].start = block + block_index[p];
+
+ p = extable[i].endpc;
+ extable[i].end = block + block_index[p];
+
+ p = extable[i].handlerpc;
+ extable[i].handler = block + block_index[p];
+ }
}
}
saved = (interfaces[s][TYPE_INT].flags | interfaces[s][TYPE_LNG].flags |
interfaces[s][TYPE_FLT].flags | interfaces[s][TYPE_DBL].flags |
interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
+
for (t = TYPE_INT; t <= TYPE_ADR; t++) {
v = &interfaces[s][t];
if (v->type >= 0) {
} /* if (type >= 0) */
} /* for t */
} /* for s */
+
maxmemuse = ifmemuse;
maxtmpintreguse = iftmpintregcnt;
maxsavintreguse = ifsavintregcnt;
maxtmpfltreguse = iftmpfltregcnt;
maxsavfltreguse = ifsavfltregcnt;
+
}
instruction *iptr = instr;
basicblock *bptr;
- b_count = block_count;
+ /* b_count = block_count; */
+
bptr = block;
- while (--b_count >= 0) {
+ while (bptr != NULL) {
+
if (bptr->flags >= BBREACHED) {
dst = bptr->instack;
reg_init_temp();
iptr = bptr->iinstr;
len = bptr->icount;
+
while (--len >= 0) {
src = dst;
dst = iptr->dst;
opcode = iptr->opc;
+
switch (opcode) {
/* pop 0 push 0 */
iptr++;
} /* while instructions */
} /* if */
- bptr++;
+ bptr = bptr->next;
} /* while blocks */
}
#else
#define COUNT(cnt)
#endif
-
+
#define STACKRESET {curstack=0;stackdepth=0;}
#define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");}
int superblockend, repeat, deadcode;
instruction *iptr = instr;
basicblock *bptr, *tbptr;
- s4 *s4ptr;
+ s4 *s4ptr;
+ void* *tptr;
+ xtable *ex;
arguments_num = 0;
new = stack;
b_index = bptr - block;
while (--len >= 0) {
opcode = iptr->opc;
+ iptr->target = NULL;
switch (opcode) {
/* pop 0 push 0 */
/* iptr[1].opc = ICMD_NOP; */
OP1_0(TYPE_INT);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
COUNT(count_pcmd_bra);
break;
iptr[2].opc = ICMD_NOP; */
OP1_0(TYPE_LNG);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
COUNT(count_pcmd_bra);
COUNT(count_pcmd_op);
COUNT(count_pcmd_bra);
OP1_0(TYPE_ADR);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
break;
#endif
OP1_0(TYPE_INT);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
break;
case ICMD_GOTO:
COUNT(count_pcmd_bra);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
SETDST;
superblockend = true;
MARKREACHED(tbptr, copy);
i = *s4ptr++; /* low */
i = *s4ptr++ - i + 1; /* high */
+
+ tptr = DMNEW(void*, i+1);
+ iptr->target = (void *) tptr;
+
+ tptr[0] = (void *) tbptr;
+ tptr++;
+
while (--i >= 0) {
tbptr = block + block_index[*s4ptr++];
+
+ tptr[0] = (void *) tbptr;
+ tptr++;
+
MARKREACHED(tbptr, copy);
}
SETDST;
tbptr = block + block_index[*s4ptr++]; /* default */
MARKREACHED(tbptr, copy);
i = *s4ptr++; /* count */
+
+ tptr = DMNEW(void*, i+1);
+ iptr->target = (void *) tptr;
+
+ tptr[0] = (void *) tbptr;
+ tptr++;
+
while (--i >= 0) {
tbptr = block + block_index[s4ptr[1]];
+
+ tptr[0] = (void *) tbptr;
+ tptr++;
+
MARKREACHED(tbptr, copy);
s4ptr += 2;
}
COUNT(count_pcmd_bra);
OP2_0(TYPE_INT);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
break;
COUNT(count_pcmd_bra);
OP2_0(TYPE_ADR);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
break;
/* iptr[1].opc = ICMD_NOP; */
OP2_0(TYPE_LNG);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
COUNT(count_pcmd_bra);
break;
case ICMD_JSR:
OP0_1(TYPE_ADR);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
tbptr->type=BBTYPE_SBR;
MARKREACHED(tbptr, copy);
OP1_0ANY;
else
count_block_stack[bptr->indepth]++;
len = bptr->icount;
- if (len <= 10)
- count_block_size_distribution[len - 1]++;
+ if (len < 10)
+ count_block_size_distribution[len]++;
else if (len <= 12)
count_block_size_distribution[10]++;
else if (len <= 14)
static void show_icmd_method()
{
- int b, i, j, last;
+ int i, j, last;
int deadcode;
s4 *s4ptr;
instruction *iptr;
-
+ basicblock *bptr;
+ void **tptr;
+ xtable *ex;
+
printf("\n");
unicode_fprint(stdout, class->name);
printf(".");
printf ("\n\nMax locals: %d\n", (int) maxlocals);
printf ("Max stack: %d\n", (int) maxstack);
- printf ("Exceptions:\n");
- for (i = 0; i < exceptiontablelength; i++) {
- printf(" L%03d ... ", block_index[extable[i].startpc]);
- printf("L%03d = ", block_index[extable[i].endpc]);
- printf("L%03d\n", block_index[extable[i].handlerpc]);
+ printf ("Exceptions (Number: %d):\n", exceptiontablelength);
+ for (ex = extable; ex != NULL; ex = ex->down) {
+ printf(" L%03d ... ", ex->start->debug_nr );
+ printf("L%03d = ", ex->end->debug_nr);
+ printf("L%03d\n", ex->handler->debug_nr);
}
printf ("Local Table:\n");
printf("\n");
}
- for (b = 0; b < block_count; b++)
- if (block[b].flags != BBDELETED) {
- deadcode = block[b].flags <= BBREACHED;
+
+ for (bptr = block; bptr != NULL; bptr = bptr->next)
+ if (bptr->flags != BBDELETED) {
+ deadcode = bptr->flags <= BBREACHED;
printf("[");
if (deadcode)
for (j = maxstack; j > 0; j--)
printf(" ? ");
else
- print_stack(block[b].instack);
- printf("] L%03d(%d):\n", b, block[b].pre_count);
- iptr = block[b].iinstr;
- i = iptr - instr;
- for (last = i + block[b].icount; i < last; i++, iptr++) {
+ print_stack(bptr->instack);
+ printf("] L%03d(%d - %d):\n", bptr->debug_nr, bptr->icount, bptr->pre_count);
+ iptr = bptr->iinstr;
+
+ for (i=0; i < bptr->icount; i++, iptr++) {
printf("[");
if (deadcode) {
for (j = maxstack; j > 0; j--)
case ICMD_IINC:
printf(" %d + %d", iptr->op1, iptr->val.i);
break;
+
+ case ICMD_IASTORE:
+ case ICMD_SASTORE:
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_LASTORE:
+ case ICMD_DASTORE:
+ case ICMD_FASTORE:
+ case ICMD_AASTORE:
+
+ case ICMD_IALOAD:
+ case ICMD_SALOAD:
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_LALOAD:
+ case ICMD_DALOAD:
+ case ICMD_FALOAD:
+ case ICMD_AALOAD:
+ if (iptr->op1 != 0)
+ printf("(opt.)");
+ break;
+
case ICMD_RET:
case ICMD_ILOAD:
case ICMD_LLOAD:
case ICMD_IF_LGE:
case ICMD_IF_LGT:
case ICMD_IF_LLE:
- printf("(%d) L%03d", iptr->val.i, block_index[iptr->op1]);
+ printf("(%d) L%03d", iptr->val.i, ((basicblock *) iptr->target)->debug_nr);
break;
case ICMD_JSR:
case ICMD_GOTO:
case ICMD_IF_LCMPLE:
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
- printf(" L%03d", block_index[iptr->op1]);
+ printf(" L%03d", ((basicblock *) iptr->target)->debug_nr);
break;
case ICMD_TABLESWITCH:
+
s4ptr = iptr->val.a;
- printf(" L%03d;", block_index[*s4ptr++]); /* default */
+ tptr = (void **) iptr->target;
+
+ printf(" L%03d;", ((basicblock *) *tptr)->debug_nr);
+ /* default */
+
+ s4ptr++;
+ tptr++;
+
j = *s4ptr++; /* low */
j = *s4ptr++ - j; /* high */
while (j >= 0) {
- printf(" L%03d", block_index[*s4ptr++]);
+ printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
+ tptr++;
j--;
}
break;
case ICMD_LOOKUPSWITCH:
s4ptr = iptr->val.a;
- printf(" L%d", block_index[*s4ptr++]); /* default */
- j = *s4ptr++; /* count */
+ tptr = (void **) iptr->target;
+
+ printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
+ s4ptr++; /* default */
+ j = *s4ptr; /* count */
+ tptr++;
+
while (--j >= 0) {
- printf(" L%03d", block_index[s4ptr[1]]);
- s4ptr += 2;
+ printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
+ tptr++;
}
break;
}
if (showdisassemble && (!deadcode)) {
printf("\n");
- i = block[b].mpc;
+ i = bptr->mpc;
s4ptr = (s4 *) (method->mcode + dseglen + i);
- for (; i < block[b + 1].mpc; i += 4, s4ptr++) {
- disassinstr(*s4ptr, i);
- }
- printf("\n");
- }
+
+ if (bptr->next != NULL) {
+ for (; i < bptr->next->mpc; i += 4, s4ptr++) {
+ disassinstr(*s4ptr, i);
+ }
+ printf("\n");
+ }
+ else {
+ for (; s4ptr < (s4 *) (method->mcode + method->mcodelength); i += 4, s4ptr++) {
+ disassinstr(*s4ptr, i);
+ }
+ printf("\n");
+ }
+ }
}
- i = block[b].mpc;
+
+ /*
+ i = bptr->mpc;
s4ptr = (s4 *) (method->mcode + dseglen + i);
if (showdisassemble && (s4ptr < (s4 *) (method->mcode + method->mcodelength))) {
printf("\n");
}
printf("\n");
}
+ */
}
Mark Probst EMAIL: cacao@complang.tuwien.ac.at
Philipp Tomsich EMAIL: cacao@complang.tuwien.ac.at
- Last Change: $Id: main.c 123 1999-01-28 19:48:49Z phil $
+ Last Change: $Id: main.c 132 1999-09-27 15:54:42Z chris $
*******************************************************************************/
#define OPT_GC1 22
#define OPT_GC2 23
#endif
+#define OPT_OLOOP 24
struct {char *name; bool arg; int value;} opts[] = {
{"classpath", true, OPT_CLASSPATH},
{"gc1", false, OPT_GC1},
{"gc2", false, OPT_GC2},
#endif
+ {"oloop", false, OPT_OLOOP},
{NULL, false, 0}
};
printf (" -log logfile ......... specify a name for the logfile\n");
printf (" -c(heck)b(ounds) ..... don't check array bounds\n");
printf (" s(ync) ....... don't check for synchronization\n");
+ printf (" -oloop ............... optimize array accesses in loops\n");
printf (" -l ................... don't start the class after loading\n");
printf (" -all ................. compile all methods, no execution\n");
#ifdef OLD_COMPILER
}
break;
+ case OPT_OLOOP:
+ opt_loops = true;
+ break;
+
default:
print_usage();
exit(10);
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
THREAD_OBJ = @THREAD_OBJ@
VERSION = @VERSION@
-EXTRA_DIST = asmpart.c calling.doc defines.h disass.c native-math.h ngen.c ngen.h threads.h types.h
-
+EXTRA_DIST = asmpart.c calling.doc defines.h disass.c \
+ native-math.h ngen.c ngen.h threads.h types.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
-all: all-redirect
+GZIP = --best
+all: Makefile
+
.SUFFIXES:
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps mips/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu mips/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
subdir = mips
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu mips/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile
-all-redirect: all-am
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-generic
-
-mostlyclean: mostlyclean-am
-
-clean-am: clean-generic mostlyclean-am
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-generic
-clean: clean-am
+clean: clean-generic mostlyclean
-distclean-am: distclean-generic clean-am
+distclean: distclean-generic clean
+ -rm -f config.status
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-generic distclean-am
+maintainer-clean: maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
-.PHONY: tags distdir info-am info dvi-am dvi check check-am \
-installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+.PHONY: tags distdir info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
noinst_LIBRARIES = libmm_new.a libmm_old.a
-libmm_new_a_SOURCES = allocator2.c allocator.h bitmap2.c bitmap2.h heap2.c lifespan.c lifespan.h mm.h
-
+libmm_new_a_SOURCES = allocator2.c allocator.h \
+ bitmap2.c bitmap2.h \
+ heap2.c \
+ lifespan.c lifespan.h \
+ mm.h
libmm_old_a_SOURCES = heap.old.c
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/@SYSDEP_DIR@
+INCLUDES=-I$(top_srcdir) -I$(top_srcdir)/@SYSDEP_DIR@
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
libmm_old_a_OBJECTS = heap.old.o
AR = ar
CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
+GZIP = --best
+DEP_FILES = .deps/allocator2.P .deps/bitmap2.P .deps/heap.old.P \
+.deps/heap2.P .deps/lifespan.P
SOURCES = $(libmm_new_a_SOURCES) $(libmm_old_a_SOURCES)
OBJECTS = $(libmm_new_a_OBJECTS) $(libmm_old_a_OBJECTS)
-all: all-redirect
+all: Makefile $(LIBRARIES)
+
.SUFFIXES:
.SUFFIXES: .S .c .o .s
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps mm/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu mm/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
maintainer-clean-noinstLIBRARIES:
-.c.o:
- $(COMPILE) -c $<
-
.s.o:
$(COMPILE) -c $<
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
- && mkid -f$$here/ID $$unique $(LISP)
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
subdir = mm
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu mm/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile $(LIBRARIES)
-all-redirect: all-am
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+ -rm -rf .deps
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+ @-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+ < .deps/$(*F).p > .deps/$(*F).P
+ @-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
- mostlyclean-tags mostlyclean-generic
-
-mostlyclean: mostlyclean-am
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
-clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
- mostlyclean-am
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \
+ clean-generic mostlyclean
-clean: clean-am
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-depend distclean-generic clean
+ -rm -f config.status
-distclean-am: distclean-noinstLIBRARIES distclean-compile \
- distclean-tags distclean-generic clean-am
-
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-generic distclean-am
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
-check-am installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info dvi \
+installcheck install-exec install-data install uninstall all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
--- /dev/null
+/* analyze.c *******************************************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties.
+
+ Contains the functions which perform the bound check removals. With
+ the loops identified, these functions scan the code for array accesses
+ that take place in loops and try to guarantee that their bounds are
+ never violated. The function to call is optimize_loops().
+
+ Authors: Christopher Kruegel EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/17/02
+
+*******************************************************************************/
+
+#ifdef LOOP_DEBUG
+
+/* Test functions -> will be removed in final release
+*/
+void show_trace(struct Trace *trace)
+{
+ if (trace != NULL) {
+ switch (trace->type) {
+ case TRACE_IVAR:
+ printf("int-var");
+ printf("\nNr.:\t%d", trace->var);
+ printf("\nValue:\t%d", trace->constant);
+ break;
+
+ case TRACE_AVAR:
+ printf("object-var");
+ printf("\nNr.:\t%d", trace->var);
+ break;
+
+ case TRACE_ALENGTH:
+ printf("array-length");
+ printf("\nNr.:\t%d", trace->var);
+ printf("\nValue:\t%d", trace->constant);
+ break;
+
+ case TRACE_ICONST:
+ printf("int-const");
+ printf("\nValue:\t%d", trace->constant);
+ break;
+
+ case TRACE_UNKNOWN:
+ printf("unknown");
+ break;
+ }
+ }
+ else
+ printf("Trace is null");
+
+ printf("\n");
+}
+void show_change(struct Changes *c)
+{
+ printf("*** Changes ***\n");
+ if (c != NULL)
+ printf("Lower/Upper Bound:\t%d/%d\n", c->lower_bound, c->upper_bound);
+ else
+ printf("Unrestricted\n");
+}
+show_varinfo(struct LoopVar *lv)
+{
+ printf(" *** Loop Info ***\n");
+ printf("Value:\t%d\n", lv->value);
+ printf("Static:\t\t%d/%d\n", lv->static_l, lv->static_u);
+ printf("D-Valid:\t%d/%d\n", lv->dynamic_l_v, lv->dynamic_u_v);
+ printf("Dynamic\t\t%d/%d\n", lv->dynamic_l, lv->dynamic_u);
+}
+void show_right_side()
+{
+ int i;
+ printf("\n *** Head *** \nType:\t");
+ show_trace(c_rightside);
+
+ printf("\n *** Nested Loops: ***\n");
+ for (i=0; i<block_count; ++i)
+ printf("%d\t", c_nestedLoops[i]);
+ printf("\n");
+
+ printf("\n *** Hierarchie: ***\n");
+ for (i=0; i<block_count; ++i)
+ printf("%d\t", c_hierarchie[i]);
+ printf("\n");
+
+
+ printf("\n *** Current Loop ***\n");
+ for (i=0; i<block_count; ++i)
+ printf("%d\t", c_current_loop[i]);
+ printf("\n");
+}
+void resultPass3()
+{
+ int i;
+ struct LoopContainer *lc = c_allLoops;
+
+ printf("\n\n****** PASS 3 ******\n\n");
+
+ while (lc != NULL) {
+ printf("Loop Analysis:\n");
+ printf("Optimize:\t%d\n", lc->toOpt);
+ printf("Modified Vars: ");
+ /*
+ for (i=0; i<lc->num_vars; ++i)
+ printf("%d ", lc->vars[i]);
+ printf("\n\n");
+ */
+ lc = lc->next;
+ }
+
+ printf("\nNested Loops:\n");
+ for (i=0; i<block_count; ++i)
+ printf("%d ", c_nestedLoops[i]);
+ printf("\n");
+ for (i=0; i<block_count; ++i)
+ printf("%d ", c_hierarchie[i]);
+ printf("\n");
+ fflush(stdout);
+}
+void show_tree(struct LoopContainer *lc, int tabs)
+{
+ int cnt;
+
+ while (lc != NULL) {
+ for (cnt = 0; cnt < tabs; ++cnt)
+ printf(" ");
+ printf("%d\n", lc->loop_head);
+
+ show_tree(lc->tree_down, tabs+1);
+
+ lc = lc->tree_right;
+ }
+}
+
+#endif
+
+#ifdef STATISTICS
+
+void show_loop_statistics()
+{
+ printf("\n\n****** LOOP STATISTICS ****** \n\n");
+ if (c_stat_or)
+ printf("Optimization cancelled by or\n");
+ else if (c_stat_exception)
+ printf("Optimization cancelled by exception\n");
+ else {
+ printf("Number of array accesses:\t%d\n", c_stat_array_accesses);
+ if (c_stat_array_accesses) {
+ printf("\nFully optimized:\t%d\n", c_stat_full_opt);
+ printf("Not optimized:\t\t%d\n", c_stat_no_opt);
+ printf("Upper optimized:\t%d\n", c_stat_upper_opt);
+ printf("Lower optimized:\t%d\n", c_stat_lower_opt);
+ }
+ }
+}
+void show_procedure_statistics()
+{
+ printf("\n\n****** PROCEDURE STATISTICS ****** \n\n");
+ printf("Number of loops:\t\t%d\n", c_stat_num_loops);
+ printf("Number of array accesses:\t%d\n", c_stat_sum_accesses);
+ if (c_stat_sum_accesses) {
+ printf("\nFully optimized:\t%d\n", c_stat_sum_full);
+ printf("Not optimized:\t\t%d\n", c_stat_sum_no);
+ printf("Upper optimized:\t%d\n", c_stat_sum_upper);
+ printf("Lower optimized:\t%d\n", c_stat_sum_lower);
+ }
+ printf("Opt. cancelled by or:\t\t%d\n", c_stat_sum_or);
+ printf("Opt. cancelled by exception:\t%d\n", c_stat_sum_exception);
+}
+
+#endif
+
+
+/* This function is used to merge two loops with the same header together.
+ A simple merge sort of the lists nodes of both loops is performed.
+*/
+void analyze_merge(struct LoopContainer *l1, struct LoopContainer *l2)
+{
+ struct LoopElement *start, *last, *le1, *le2;
+ /* start and last are pointers to the newly built list, le1 and le2 step */
+ /* step through the lists, that have to be merged. */
+
+ le1 = l1->nodes;
+ le2 = l2->nodes;
+
+ /* start a simple merge sort of the nodes of both loops. These lists are */
+ /* already sorted, so merging is easy. */
+ if (le1->node < le2->node) {
+ start = last = le1;
+ le1 = le1->next;
+ }
+ else if (le1->node == le2->node) {
+ start = last = le1;
+ le1 = le1->next;
+ le2 = le2->next;
+ }
+ else {
+ start = last = le2;
+ le2 = le2->next;
+ }
+
+ /* while the first loop != NULL, depending of the first element of second */
+ /* loop, add new node to result list */
+ while (le1 != NULL) {
+
+ if (le2 == NULL) {
+ last->next = le1;
+ break;
+ }
+ if (le1->node < le2->node) {
+ last->next = le1;
+ le1 = le1->next;
+ }
+ else if (le1->node == le2->node) {
+ last->next = le1;
+ le1 = le1->next;
+ le2 = le2->next;
+ last = last->next;
+ }
+ else {
+ last->next = le2;
+ le2 = le2->next;
+ last = last->next;
+ }
+ }
+
+ last->next = le2;
+}
+
+
+/* This function is used to merge loops with the same header node to a single
+ one. O(n^2) of number of loops. This merginig is necessary, because the loop
+ finding algorith sometimes (eg. when loopbody ends with a if-else construct)
+ reports a single loop as two loops with the same header node.
+*/
+void analyze_double_headers()
+{
+ int toCheck;
+ struct LoopContainer *t1, *t2, *t3;
+
+ t1 = c_allLoops;
+
+ while (t1 != NULL) { /* for all loops do */
+ toCheck = t1->loop_head; /* get header node */
+ t2 = t1->next;
+
+ while (t2 != NULL) { /* compare it to headers of rest */
+ if (t2->loop_head == toCheck) {
+
+ /* found overlapping loops -> merge them together */
+ /* printf("C_INFO: found overlapping loops - merging"); */
+ analyze_merge(t1, t2);
+
+ /* remove second loop from the list of all loops */
+ t3 = t1;
+ while (t3->next != t2)
+ t3 = t3->next;
+ t3->next = t2->next;
+ }
+ t2 = t2->next;
+ }
+
+ t1 = t1->next;
+ }
+}
+
+
+/* After the hierarchie of loops has been built, we have to insert the exceptions
+ into this tree. The exception ex is inserted into the subtree pointed to by
+ LoopContainer lc.
+*/
+void insert_exception(struct LoopContainer *lc, xtable *ex)
+{
+ struct LoopContainer *temp;
+ struct LoopElement *le;
+
+#ifdef LOOP_DEBUG
+ /* printf("insert_exception called with %d-%d and loop %d\n", ex->start->debug_nr, ex->end->debug_nr, lc->loop_head); */
+#endif
+
+ /* if child node is reached immediately insert the exception into the tree */
+ if (lc->tree_down == NULL) {
+ ex->next = lc->exceptions;
+ lc->exceptions = ex;
+ }
+ else {
+ /* if we are inside the tree, there are two possibilities: */
+ /* 1. the exception is inside a nested loop or */
+ /* 2. in the loop body of the current loop */
+
+ /* check all children (= nested loops) */
+ temp = lc->tree_down;
+
+ while (temp != NULL) {
+
+ le = temp->nodes;
+ while (le != NULL) {
+
+#ifdef LOOP_DEBUG
+ printf("%d.%d\n", le->node, block_index[ex->startpc]);
+#endif
+ /* if the start of the exception is part of the loop, the whole */
+ /* exception must be part of the loop */
+ if (le->node == block_index[ex->startpc])
+ break;
+ le = le->next;
+ }
+
+ /* Exception is part of a nested loop (Case 1) -> insert it there */
+ if (le != NULL) {
+ insert_exception(temp, ex);
+ return;
+ }
+ else if ((temp->loop_head >= block_index[ex->startpc]) && (temp->loop_head < block_index[ex->endpc])) {
+
+ /* optimization: if nested loop is part of the exception, the */
+ /* exception cannot be part of a differnet nested loop. */
+ ex->next = lc->exceptions;
+ lc->exceptions = ex;
+ return;
+ }
+ else
+ temp = temp->tree_right;
+ }
+
+ /* Exception is not contained in any nested loop (Case 2) */
+ if (temp == NULL) {
+ ex->next = lc->exceptions;
+ lc->exceptions = ex;
+ }
+ }
+}
+
+
+/* This function builds a loop hierarchie. The header node of the innermost loop,
+ each basic block belongs to, is stored in the array c_nestedLoops. The array
+ c_hierarchie stores the relationship between differnt loops in as follows:
+ Each loop, that is a nested loop, stores its direct surrounding loop as a
+ parent. Top level loops have no parents.
+*/
+void analyze_nested()
+{
+ /* i/count/tmp are counters */
+ /* toOverwrite is used while loop hierarchie is built (see below) */
+ int i, count, header, toOverwrite, tmp, len;
+
+ /* first/last are used during topological sort to build ordered loop list */
+ struct LoopContainer *first, *last, *start, *t, *temp;
+
+ /* Used to step through all nodes of a loop. */
+ struct LoopElement *le;
+
+ /* init global structures */
+ c_nestedLoops = DMNEW(int, block_count);
+ c_hierarchie = DMNEW(int, block_count);
+ for (i=0; i<block_count; ++i) {
+ c_nestedLoops[i] = -1;
+ c_hierarchie[i] = -1;
+ }
+
+ /* if there are no optimizable loops -> return */
+ if (c_allLoops == NULL)
+ return;
+
+ temp = c_allLoops;
+ while (temp != NULL) { /* for all loops, do */
+ header = temp->loop_head;
+
+ /* toOverwrite is number of current parent loop (-1 if none) */
+ toOverwrite = c_nestedLoops[header];
+
+ c_hierarchie[header] = toOverwrite;
+
+ if (toOverwrite == header) /* check for loops with same header */
+ printf("C_ERROR: Loops have same header\n");
+
+ le = temp->nodes;
+ while (le != NULL) { /* for all loop nodes, do */
+ tmp = c_nestedLoops[le->node];
+
+ /* if node is part of parent loop -> overwrite it with nested */
+ if (tmp == toOverwrite)
+ c_nestedLoops[le->node] = header;
+ else {
+ c_hierarchie[tmp] = header;
+#ifdef LOOP_DEBUG
+ /* printf("set head of %d to %d", tmp, header); */
+#endif
+ }
+
+ le = le->next;
+ }
+
+ temp = temp->next;
+ }
+
+ /* init root of hierarchie tree */
+ root = DMNEW(struct LoopContainer, 1);
+ LoopContainerInit(root, -1);
+
+ /* obtain parent pointer and build hierarchie tree */
+ start = c_allLoops;
+ while (start != NULL) {
+
+ /* look for parent of loop pointed at by start */
+ first = c_allLoops;
+ while (first != NULL) {
+
+ /* the parent of the loop, pointed at by start has been found */
+ if (first->loop_head == c_hierarchie[start->loop_head]) {
+#ifdef LOOP_DEBUG
+ /* printf("set parent to pointer\n"); */
+#endif
+
+ start->parent = first;
+ start->tree_right = first->tree_down;
+ first->tree_down = start;
+
+ break;
+ }
+ first = first->next;
+ }
+
+ /* no parent loop found, set parent to root */
+ if (first == NULL) {
+#ifdef LOOP_DEBUG
+ /* printf("set parent to root\n"); */
+#endif
+
+ start->parent = root;
+ start->tree_right = root->tree_down;
+ root->tree_down = start;
+ }
+ /* if a parent exists, increase this nodes indegree */
+ else
+ start->parent->in_degree += 1;
+
+ start = start->next;
+ }
+
+ /* insert exceptions into tree */
+#ifdef LOOP_DEBUG
+ printf("--- Showing tree ---\n");
+ show_tree(root, 0);
+ printf(" --- End ---\n");
+#endif
+ for (len = 0; len < exceptiontablelength; ++len)
+ insert_exception(root, extable + len);
+
+
+ /* determine sequence of loops for optimization by topological sorting them */
+
+ /* init queue */
+ start = NULL;
+ temp = c_allLoops;
+ while (temp != NULL) {
+
+ /* a loops with indegree == 0 are pushed onto the stack */
+ if (temp->in_degree == 0) {
+ t = temp->next;
+ temp->next = start;
+ start = temp;
+ }
+ else
+ t = temp->next;
+
+ temp = t;
+ }
+
+ /* sort loops */
+ first = last = start;
+ start = start->next;
+
+ if (last == NULL) {
+ printf("C_ERROR: loops are looped\n");
+ exit(-1);
+ }
+
+ /* pop each node from the stack and decrease its parents indegree by one */
+ /* when the parents indegree reaches zero, push it onto the stack as well */
+ if ((last->parent != root) && (--last->parent->in_degree == 0)) {
+ last->parent->next = start;
+ start = last->parent;
+ }
+ while (start != NULL) {
+
+ last->next = start;
+
+ start = start->next;
+ last = last->next;
+
+ if ((last->parent != root) && (--last->parent->in_degree == 0)) {
+ last->parent->next = start;
+ start = last->parent;
+ }
+ }
+
+ last->next = NULL;
+ c_allLoops = first;
+
+#ifdef LOOP_DEBUG
+ printf("*** Hierarchie Results \n");
+ while (first != NULL) {
+ printf("%d ", first->loop_head);
+ first = first->next;
+ }
+ printf("\n");
+ fflush(stdout);
+#endif
+}
+
+/* This function is used to add variables that occur as index variables in
+ array accesses (ARRAY_INDEX) or as variables, that change their value (VAR_MOD)
+ to the list of interesting vars (c_loopvars) for the current loop.
+*/
+void add_to_vars(int var, int type, int direction)
+{
+ struct LoopVar *lv;
+
+ /* printf("Added to vars %d %d %d\n", var, type, direction); */
+ lv = c_loopvars;
+ while (lv != NULL) { /* check if var has been previously added */
+ if (lv->value == var) {
+ if (type == ARRAY_INDEX)
+ lv->index = 1; /* var is used as index */
+ else if (type == VAR_MOD) {
+ lv->modified = 1; /* var is used in assignment */
+ switch (direction) { /* how was var modified ? */
+ case D_UP:
+ lv->static_u = 0; /* incremented, no static upper */
+ break; /* bound can be guaranteeed */
+ case D_DOWN:
+ lv->static_l = 0; /* decremented, no static lower */
+ break; /* bound can be guaranteeed */
+ case D_UNKNOWN:
+ lv->static_u = lv->static_l = 0;
+ break; /* no info at all */
+ default:
+ printf("C_ERROR: unknown direction\n");
+ break;
+ }
+ }
+ return;
+ }
+ lv = lv->next;
+ }
+
+ /* variable is not found in list -> add variable to list */
+ lv = DNEW(struct LoopVar);
+
+ lv->value = var;
+ if (type == ARRAY_INDEX) {
+ lv->index = 1;
+ lv->static_u = lv->static_l = 1; /* array index -> var not modified */
+ }
+ else if (type == VAR_MOD) {
+ lv->modified = 1;
+ switch (direction) { /* var is used in assignment -> set */
+ case D_UP: /* proper static bounds */
+ lv->static_u = 0; lv->static_l = 1;
+ break;
+ case D_DOWN:
+ lv->static_u = 1; lv->static_l = 0;
+ break;
+ case D_UNKNOWN:
+ lv->static_u = lv->static_l = 0;
+ break;
+ default:
+ printf("C_ERROR: unknown direction\n");
+ break;
+ }
+ }
+
+ /* !! strange
+ lv->modified = 0;
+ */
+
+ /* no dynamic bounds have been determined so far */
+ lv->dynamic_l = lv->dynamic_l_v = lv->dynamic_u = lv->dynamic_u_v = 0;
+
+ lv->next = c_loopvars; /* add var to list */
+ c_loopvars = lv;
+}
+
+/* This function checks, whether a given loop with header node contains array
+ accesses. If so, it returns 1, else it returns 0 and the loops needs no
+ further consideration in the optimization process. When array accesses are
+ found, a list of all variables, that are used as array index, is built and
+ stored in c_loopvars. For all variables (integer), which values are changed,
+ a flag in c_var_modified is set.
+*/
+int analyze_for_array_access(int node)
+{
+ basicblock bp;
+ instruction *ip;
+ int ic, i, j, access;
+ struct depthElement *d;
+ struct Trace *t;
+
+ if (c_toVisit[node] > 0) { /* node has not been visited yet */
+ c_toVisit[node] = 0;
+
+ bp = block[node]; /* prepare an instruction scan */
+ ip = bp.iinstr;
+ ic = bp.icount;
+
+ access = 0; /* number of array accesses in loop */
+
+ for (i=0; i<ic; ++i, ++ip) { /* for each instruction, check opcode */
+ switch (ip->opc) {
+ case ICMD_IASTORE: /* array store */
+ case ICMD_LASTORE:
+ case ICMD_FASTORE:
+ case ICMD_DASTORE:
+ case ICMD_AASTORE:
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_SASTORE:
+ t = tracing(&bp, i-1, 1); /* try to identify index variable */
+
+ if (t->type == TRACE_IVAR) {
+ /* if it is a variable, add it to list of index variables */
+ add_to_vars(t->var, ARRAY_INDEX, D_UNKNOWN);
+ access++;
+ }
+ else if (t->type == TRACE_ICONST)
+ access++;
+ break;
+
+ case ICMD_IALOAD: /* array load */
+ case ICMD_LALOAD:
+ case ICMD_FALOAD:
+ case ICMD_DALOAD:
+ case ICMD_AALOAD:
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_SALOAD:
+ t = tracing(&bp, i-1, 0); /* try to identify index variable */
+
+ if (t->type == TRACE_IVAR) {
+ /* if it is a variable, add it to list of index variables */
+ add_to_vars(t->var, ARRAY_INDEX, D_UNKNOWN);
+ access++;
+ }
+ else if (t->type == TRACE_ICONST)
+ access++;
+ break;
+
+ case ICMD_ISTORE: /* integer store */
+ c_var_modified[ip->op1] = 1;
+
+ /* try to find out, how it was modified */
+ t = tracing(&bp, i-1, 0);
+ if (t->type == TRACE_IVAR) {
+ if ((t->constant > 0) && (t->var == ip->op1))
+ /* a constant was added to the same var */
+ add_to_vars(t->var, VAR_MOD, D_UP);
+ else if (t->var == ip->op1)
+ /* a constant was subtracted from the same var */
+ add_to_vars(t->var, VAR_MOD, D_DOWN);
+ else
+ add_to_vars(t->var, VAR_MOD, D_UNKNOWN);
+ }
+ else
+ add_to_vars(ip->op1, VAR_MOD, D_UNKNOWN);
+ break;
+
+ case ICMD_IINC: /* simple add/sub of a constant */
+ c_var_modified[ip->op1] = 1;
+
+ if (ip->val.i > 0)
+ add_to_vars(ip->op1, VAR_MOD, D_UP);
+ else
+ add_to_vars(ip->op1, VAR_MOD, D_DOWN);
+ break;
+
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_ASTORE:
+ c_var_modified[ip->op1] = 1;
+ break;
+
+ default:
+ }
+ }
+
+ d = c_dTable[node];
+ while (d != NULL) { /* check all successors of block */
+ access += analyze_for_array_access(d->value);
+ d = d->next;
+ }
+
+ return access;
+ }
+ else
+ return 0;
+}
+
+/* This function scans the exception graph structure to find modifications of
+ array index variables of the current loop. If any modifications are found,
+ 1 is returned, else 0.
+*/
+int quick_scan(int node)
+{
+ basicblock bp;
+ instruction *ip;
+ int count, i;
+ struct LoopVar *lv;
+ struct depthElement *d;
+
+ /* printf("QS: %d - %d\n", node, c_exceptionVisit[node]); */
+
+
+ if (c_exceptionVisit[node] > 0) { /* node is part of exception graph */
+ c_exceptionVisit[node] = -1;
+
+ bp = block[node]; /* setup scan of all instructions */
+ ip = bp.iinstr;
+ count = bp.icount;
+
+ for (i=0; i<count; ++i, ++ip) { /* for each instruction do */
+ switch (ip->opc) {
+ case ICMD_ISTORE:
+ case ICMD_IINC: /* a variable is modified */
+
+ lv = c_loopvars; /* is it an array index var ? */
+ while (lv != NULL) {
+ if ((lv->index) && (lv->value == ip->op1))
+ return 1; /* yes, so return 1 */
+ lv = lv->next;
+ }
+ break;
+ }
+ }
+
+ d = c_exceptionGraph[node]; /* check all successor nodes */
+ while (d != NULL) {
+ if (quick_scan(d->value) > 0)
+ return 1; /* if an access is found return 1 */
+ d = d->next;
+ }
+
+ return 0; /* nothing found, so return 0 */
+ }
+ else
+ return 0;
+}
+
+/* This function returns 1, when the condition of the loop contains
+ or statements or when an array index variable is modified in any
+ catch block within the loop.
+*/
+int analyze_or_exceptions(int head, struct LoopContainer *lc)
+{
+ struct depthElement *d, *tmp, *tmp2;
+ int i, j, k, value, flag, count;
+ struct LoopElement *le;
+
+ d = c_dTable[head];
+ count = flag = 0;
+
+ /* analyze for or-statements */
+#ifdef LOOP_DEBUG
+ printf("*** Analyze for OR ... ");
+ fflush(stdout);
+#endif
+
+ while (d != NULL) { /* for all successor nodes check if they */
+ value = d->value; /* are part of the loop */
+
+ le = lc->nodes;
+
+ while (le != NULL) {
+ if (le->node == value)
+ break;
+ le = le->next;
+ }
+
+ if (le == NULL) /* node is not part of the loop */
+ ++flag;
+
+ d = d->next;
+ ++count;
+ }
+
+ if ((count > 1) && (flag == 0)){/* if all successors part of the loop, exit */
+#ifdef STATISTICS
+ c_stat_or++;
+#endif
+ return 0;
+ }
+
+ /* check for exceptions */
+ /* printf("done\n*** Analyze for EXCEPTIONS(%d) . ", exceptiontablelength); */
+
+ if (!exceptiontablelength) /* when there are no exceptions, exit */
+ return 1;
+
+ if ((c_exceptionGraph = (struct depthElement **) malloc(sizeof(struct depthElement *) * block_count)) == NULL)
+ c_mem_error();
+ if ((c_exceptionVisit = (int *) malloc(sizeof(int) * block_count)) == NULL)
+ c_mem_error();
+
+ for (k=0; k<block_count; ++k) {
+ c_exceptionVisit[k] = -1;
+ c_exceptionGraph[k] = NULL;
+ }
+
+
+ /* for all nodes that start catch block check whether they are part of loop */
+ for (i = 0; i < c_old_xtablelength; i++) {
+ value = block_index[extable[i].startpc];
+
+ le = lc->nodes;
+ while (le != NULL) {
+
+ if (le->node == value) { /* exception is in loop */
+#ifdef LOOP_DEBUG
+ printf("C_INFO: Loop contains exception\n");
+ fflush(stdout);
+#endif
+
+ /* build a graph structure, that contains all nodes that are */
+ /* part of the catc block */
+ dF_Exception(-1, block_index[extable[i].handlerpc]);
+
+ /* if array index variables are modified there, return 0 */
+ if (quick_scan(block_index[extable[i].handlerpc]) > 0) {
+#ifdef STATISTICS
+ c_stat_exception++;
+#endif
+ /* printf("C_INFO: loopVar modified in exception\n"); */
+ return 0;
+ }
+ }
+ le = le->next;
+ }
+ }
+
+#ifdef LOOP_DEBUG
+ printf("none ... done\n");
+ fflush(stdout);
+#endif
+ return 1;
+}
+
+/* This function sets a flag in c_var_modified for all variables that have
+ been found as part of an assigment in the loop.
+*/
+void scan_global_list()
+{
+ struct LoopVar *lv;
+ lv = c_loopvars;
+
+ while (lv != NULL) {
+ if (lv->modified)
+ c_var_modified[lv->value] = 1;
+ lv = lv->next;
+ }
+}
+
+/* This function analyses the condition in the loop header and trys to find
+ out, whether some dynamic guarantees can be set up.
+*/
+void init_constraints(int head)
+{
+ basicblock bp;
+ instruction *ip;
+ int ic, l_mod, r_mod, changed, operand;
+ struct Trace *left, *right, *th;
+ struct LoopVar *lv_left, *lv_right, *lh;
+
+ bp = block[head];
+ ic = bp.icount;
+ ip = bp.iinstr+(ic-1); /* set ip to last instruction in header node */
+
+ switch (ip->opc) { /* check op-code */
+
+ /* comparison against constant value */
+ case ICMD_IFEQ: /* ..., value ==> ... */
+ case ICMD_IFLT: /* ..., value ==> ... */
+ case ICMD_IFLE: /* ..., value ==> ... */
+ case ICMD_IFGT: /* ..., value ==> ... */
+ case ICMD_IFGE: /* ..., value ==> ... */
+ /* op1 = target JavaVM pc, val.i = constant */
+
+ left = tracing(&bp, ic-2, 0); /* analyse left arg., right is constant */
+ right = create_trace(TRACE_ICONST, -1, ip->val.i, 0);
+ break;
+
+ /* standard comparison */
+ case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
+
+ left = tracing(&bp, ic-2, 1); /* get left and right argument */
+ right = tracing(&bp, ic-2, 0);
+ break;
+
+ /* other condition */
+ default:
+ left = create_trace(TRACE_UNKNOWN, -1, 0, 0);
+ right = create_trace(TRACE_UNKNOWN, -1, 0, 0);
+ break;
+ }
+
+ /* analyse left and right side of comparison */
+ l_mod = r_mod = 0;
+
+ if (left->type == TRACE_IVAR) { /* is a loop variable on left side ? */
+ lv_left = c_loopvars;
+ while (lv_left != NULL) {
+ if (lv_left->value == left->var) {
+ l_mod = lv_left->modified; /* yes, but has it been modified ? */
+ break;
+ }
+ lv_left = lv_left->next;
+ }
+ }
+
+ if (right->type == TRACE_IVAR){ /* is a loop variable on right side ? */
+ lv_right = c_loopvars;
+ while (lv_right != NULL) {
+ if (lv_right->value == right->var) {
+ r_mod = lv_right->modified; /* yes, but has it been modified ? */
+ break;
+ }
+ lv_right = lv_right->next;
+ }
+ }
+
+ if ((l_mod - r_mod) == 0) { /* both 1 or both 0 -> no dynamic contraints*/
+ c_rightside = NULL; /* possible */
+ return;
+ }
+
+ /* to simplify processing, make the left side the one, that contains the */
+ /* modified variable */
+ if (r_mod > l_mod) {
+ th = left; left = right; right = th;
+ lh = lv_left; lv_left = lv_right; lv_right = lh;
+ changed = 1; /* set changed to true */
+ }
+ else
+ changed = 0; /* no change needed */
+
+ /* make sure that right side's value does not change during loop execution */
+ if (right->type == TRACE_UNKNOWN) {
+ c_rightside = NULL;
+ return;
+ }
+
+ /* determine operands: */
+ /* for further explaination a is modified, b nonmodified var */
+ switch (ip->opc) { /* check opcode again */
+ case ICMD_IFEQ: /* ..., value ==> ... */
+ case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
+ operand = OP_EQ; /* a == b */
+ break;
+
+ case ICMD_IFLE: /* ..., value ==> ... */
+ case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
+ if (changed)
+ operand = OP_GE; /* b<=a -> a>=b */
+ else {
+ operand = OP_LT; /* a<=b -> a<(b+1) */
+ if (left->constant != 0)
+ left->constant -= 1;
+ else
+ right->constant += 1;
+ }
+ break;
+
+ case ICMD_IFLT: /* ..., value ==> ... */
+ case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
+ if (changed) {
+ operand = OP_GE; /* b<a -> a>=(b+1) */
+ if (left->constant != 0)
+ left->constant -= 1;
+ else
+ right->constant += 1;
+ }
+ else
+ operand = OP_LT; /* a<b -> a<b */
+ break;
+
+ case ICMD_IFGT: /* ..., value ==> ... */
+ case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
+ if (changed)
+ operand = OP_LT; /* b>a -> a<b */
+ else {
+ operand = OP_GE; /* a>b -> a>=(b+1) */
+ if (left->constant != 0)
+ left->constant -= 1;
+ else
+ right->constant += 1;
+ }
+ break;
+
+ case ICMD_IFGE: /* ..., value ==> ... */
+ case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
+ if (changed) {
+ operand = OP_LT; /* b>=a -> a<(b+1) */
+ if (left->constant != 0)
+ left->constant -= 1;
+ else
+ right->constant += 1;
+ }
+ else
+ operand = OP_GE; /* a>=b -> a>=b */
+ break;
+
+ default:
+ printf("C_ERROR: debugging error 0x00\n");
+ }
+
+
+ /* NOW: left/lv_left -> loopVar */
+ /* right/lv_right -> const, nonmod. var, arraylength */
+ switch (operand) { /* check operand */
+ case OP_EQ:
+ lv_left->dynamic_u_v = 1; /* upper + lower bound tested */
+ lv_left->dynamic_l_v = 1;
+
+ lv_left->dynamic_l = lv_left->dynamic_u = left->constant;
+ break;
+
+ case OP_LT:
+ lv_left->dynamic_u_v = 1; /* upper bound tested */
+
+ lv_left->dynamic_u = left->constant;
+ break;
+
+ case OP_GE:
+ lv_left->dynamic_l_v = 1; /* lower bound tested */
+
+ lv_left->dynamic_l = left->constant;
+ break;
+
+ default:
+ printf("C_ERROR: debugging error 0x01\n");
+ }
+
+ c_rightside = right;
+
+ switch (c_rightside->type) {
+ case TRACE_ICONST:
+ c_rs_needed_instr = 1;
+ break;
+ case TRACE_ALENGTH:
+ c_rs_needed_instr = 2;
+ break;
+ case TRACE_IVAR:
+ c_rs_needed_instr = 3;
+ break;
+ default:
+ printf("C_ERROR: wrong right-side type\n");
+ }
+}
+
+/* This function is needed to add and record new static tests (before loop
+ entry) of variables to make guaratees for index variables. type states
+ the kind of the test. arrayRef is the array, which length is tested
+ against, varRef is the variable, that is testes and constant is the
+ constant value, that is tested.
+*/
+void add_new_constraint(int type, int arrayRef, int varRef, int constant)
+{
+ struct Constraint *tc;
+
+ switch (type) {
+ case TEST_ZERO: /* a variable is tested against a const */
+
+ tc = c_constraints[varRef]; /* does a test already exist for this var ? */
+ while (tc != NULL) {
+ if (tc->type == TEST_ZERO) {
+ if (constant < tc->constant)
+ tc->constant = constant;
+ return; /* yes. update constant and return */
+ }
+ tc = tc->next;
+ }
+
+ /* insert a new test for this variable */
+ if ((tc = (struct Constraint *) malloc(sizeof(struct Constraint))) == NULL)
+ c_mem_error();
+ tc->type = TEST_ZERO;
+ tc->varRef = varRef;
+ tc->constant = constant;
+ tc->next = c_constraints[varRef];
+ c_constraints[varRef] = tc;
+ c_needed_instr += 3;
+
+ break;
+
+ case TEST_ALENGTH: /* variable is tested against array length */
+
+ tc = c_constraints[varRef]; /* does a test already exist for this var ? */
+ while (tc != NULL) {
+ if ((tc->type == TEST_ALENGTH) && (tc->arrayRef == arrayRef)) {
+ if (constant > tc->constant)
+ tc->constant = constant;
+ return; /* yes. update constant and return */
+ }
+ tc = tc->next;
+ }
+
+ /* insert a new test for this variable */
+ if ((tc = (struct Constraint *) malloc(sizeof(struct Constraint))) == NULL)
+ c_mem_error();
+ tc->type = TEST_ALENGTH;
+ tc->arrayRef = arrayRef;
+ tc->varRef = varRef;
+ tc->constant = constant;
+ tc->next = c_constraints[varRef];
+ c_constraints[varRef] = tc;
+ c_needed_instr += 6;
+
+ /* if arrayRef is not already tested against null, insert that test */
+ if (!(c_null_check[arrayRef])) {
+ c_null_check[arrayRef] = 1;
+ c_needed_instr +=2;
+ }
+
+ break;
+
+ case TEST_CONST_ZERO:
+ /* done earlier */
+ break;
+
+ case TEST_CONST_ALENGTH: /* a const is tested against array length */
+
+ /* does a test already exist for this array */
+ tc = c_constraints[maxlocals];
+ while (tc != NULL) {
+ if ((tc->type == TEST_CONST_ALENGTH) && (tc->arrayRef == arrayRef)) {
+ if (constant > tc->constant)
+ tc->constant = constant;
+ return; /* yes. update constant and return */
+ }
+ tc = tc->next;
+ }
+
+ /* insert a new test for this array */
+ if ((tc = (struct Constraint *) malloc(sizeof(struct Constraint))) == NULL)
+ c_mem_error();
+ tc->type = TEST_CONST_ALENGTH;
+ tc->arrayRef = arrayRef;
+ tc->constant = constant;
+ tc->next = c_constraints[maxlocals];
+ c_constraints[maxlocals] = tc;
+ c_needed_instr += 4;
+
+ /* if arrayRef is not already tested against null, insert that test */
+ if (!(c_null_check[arrayRef])) {
+ c_null_check[arrayRef] = 1;
+ c_needed_instr +=2;
+ }
+
+ break;
+
+ case TEST_UNMOD_ZERO: /* test unmodified var against constant */
+
+ /* search if test already exists */
+ tc = c_constraints[varRef];
+ while (tc != NULL) {
+ if (tc->type == TEST_UNMOD_ZERO) {
+ if (constant < tc->constant)
+ tc->constant = constant;
+ return; /* yes, so update constant */
+ }
+ tc = tc->next;
+ }
+
+ /* else, a new test is inserted */
+ if ((tc = (struct Constraint *) malloc(sizeof(struct Constraint))) == NULL)
+ c_mem_error();
+ tc->type = TEST_UNMOD_ZERO;
+ tc->varRef = varRef;
+ tc->constant = constant;
+ tc->next = c_constraints[varRef];
+ c_constraints[varRef] = tc;
+ c_needed_instr += 3;
+
+ break;
+
+ case TEST_UNMOD_ALENGTH: /* test unmodified var against array length */
+
+ /* search if test alreay exists */
+ tc = c_constraints[varRef];
+ while (tc != NULL) {
+ if ((tc->type == TEST_UNMOD_ALENGTH) && (tc->arrayRef == arrayRef)) {
+ if (constant > tc->constant)
+ tc->constant = constant;
+ return; /* yes, so modify constants */
+ }
+ tc = tc->next;
+ }
+
+ /* create new entry */
+ if ((tc = (struct Constraint *) malloc(sizeof(struct Constraint))) == NULL)
+ c_mem_error();
+ tc->type = TEST_UNMOD_ALENGTH;
+ tc->varRef = varRef;
+ tc->arrayRef = arrayRef;
+ tc->constant = constant;
+ tc->next = c_constraints[varRef];
+ c_constraints[varRef] = tc;
+ c_needed_instr += 6;
+
+ /* if arrayRef is not already tested against null, insert that test */
+ if (!(c_null_check[arrayRef])) {
+ c_null_check[arrayRef] = 1;
+ c_needed_instr +=2;
+ }
+
+ break;
+
+ case TEST_RS_ZERO: /* test right side of the loop condition */
+ /* against a constant - needed by dynamic */
+ /* checks */
+ /*!! varRef -> maxlocals */
+ /* search if test already exists */
+ tc = c_constraints[maxlocals];
+ while (tc != NULL) {
+ if (tc->type == TEST_RS_ZERO) {
+ if (constant < tc->constant)
+ tc->constant = constant;
+ return; /* yes, so modify constants */
+ }
+ tc = tc->next;
+ }
+
+ /* create new entry */
+ if ((tc = (struct Constraint *) malloc(sizeof(struct Constraint))) == NULL)
+ c_mem_error();
+ tc->type = TEST_RS_ZERO;
+ tc->constant = constant;
+ tc->next = c_constraints[maxlocals];
+ c_constraints[maxlocals] = tc;
+ c_needed_instr += (2 + c_rs_needed_instr);
+
+ /* if arrayRef on right side is not already tested against null, */
+ /* insert that test */
+ if ((c_rightside->type == TRACE_ALENGTH) && (!(c_null_check[c_rightside->var]))) {
+ c_null_check[c_rightside->var] = 1;
+ c_needed_instr +=2;
+ }
+
+ break;
+
+ case TEST_RS_ALENGTH: /* test right side of the loop condition */
+ /* against array length - needed by dynamic */
+ /* checks */
+ /*!! varRef -> maxlocals */
+ /* search if test already exists */
+ tc = c_constraints[maxlocals];
+ while (tc != NULL)
+ {
+ if ((tc->type == TEST_RS_ALENGTH) && (tc->arrayRef == arrayRef))
+ {
+ if (constant > tc->constant)
+ tc->constant = constant;
+ return; /* yes, so modify constants */
+ }
+ tc = tc->next;
+ }
+
+ /* create new entry */
+ if ((tc = (struct Constraint *) malloc(sizeof(struct Constraint))) == NULL)
+ c_mem_error();
+ tc->type = TEST_RS_ALENGTH;
+ tc->arrayRef = arrayRef;
+ tc->constant = constant;
+ tc->next = c_constraints[maxlocals];
+ c_constraints[maxlocals] = tc;
+ c_needed_instr += (3 + c_rs_needed_instr);
+
+ /* if arrayRef is not already tested against null, insert that test */
+ if (!(c_null_check[arrayRef])) {
+ c_null_check[arrayRef] = 1;
+ c_needed_instr +=2;
+ }
+
+ /* if arrayRef on right side is not already tested against null, */
+ /* insert that test */
+ if ((c_rightside->type == TRACE_ALENGTH) && (!(c_null_check[c_rightside->var]))) {
+ c_null_check[c_rightside->var] = 1;
+ c_needed_instr +=2;
+ }
+ break;
+
+ }
+}
+
+/* This functions adds new static (before loop enry) tests of variables to the
+ program to be able to guarantee certain values for index variables in array
+ access (to safely remove bound checks).
+*/
+int insert_static(int arrayRef, struct Trace *index, struct Changes *varChanges, int special)
+{
+ struct Constraint *tc;
+ struct LoopVar *lv;
+ int varRef;
+ int high, low;
+
+ /* printf("insert static check - %d\n", arrayRef);
+ show_trace(index);
+ show_change(varChanges);
+ */
+
+ if (varChanges == NULL) { /* the variable hasn't changed / const */
+ if ((varChanges = (struct Changes *) malloc(sizeof(struct Changes))) == NULL)
+ c_mem_error();
+ varChanges->lower_bound = varChanges->upper_bound = 0;
+ }
+
+ switch (index->type) { /* check index type */
+ case TRACE_IVAR: /* it is a variable */
+ if (index->neg < 0) { /* if it's a negated var, return */
+#ifdef STATISTICS
+ c_stat_no_opt++;
+#endif
+ return OPT_NONE;
+ }
+
+ varRef = index->var;
+ high = low = 0;
+
+ if (c_var_modified[varRef]) { /* volatile var */
+
+ lv = c_loopvars; /* get reference to loop variable */
+
+ while ((lv != NULL) && (lv->value != varRef))
+ lv = lv->next;
+ if (lv == NULL)
+ printf("C_ERROR: debugging error 0x02\n");
+
+ /* show_varinfo(lv); */
+
+ /* check existing static bounds and add new contraints on variable */
+ /* to possibly remove bound checks */
+ if (lv->static_l) {
+ /* the var is never decremented, so we add a static test againt */
+ /* constant */
+ if (varChanges->lower_bound > varChanges->upper_bound)
+ add_new_constraint(TEST_ZERO, arrayRef, varRef, index->constant);
+ else
+ add_new_constraint(TEST_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant);
+ low = 1;
+ }
+ else if ((lv->dynamic_l_v) && (!special)) {
+ /* the variable is decremented, but it is checked against a */
+ /* bound in the loop condition */
+ if (varChanges->lower_bound <= varChanges->upper_bound) {
+ add_new_constraint(TEST_RS_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant+lv->dynamic_l);
+ low = 1;
+ }
+ }
+
+ if (lv->static_u) {
+ /* the var is never incremented, so we add a static test againt */
+ /* constant */
+ if (varChanges->lower_bound > varChanges->upper_bound)
+ add_new_constraint(TEST_ALENGTH, arrayRef, varRef, index->constant);
+ else
+ add_new_constraint(TEST_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant);
+ high = 1;
+ }
+ else if ((lv->dynamic_u_v) && (!special)) {
+ /* the variable is decremented, but it is checked against a */
+ /* bound in the loop condition */
+ if (varChanges->lower_bound <= varChanges->upper_bound) {
+ add_new_constraint(TEST_RS_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant+lv->dynamic_u);
+ high = 1;
+ }
+ }
+ }
+ else { /* the var is never modified at all */
+ add_new_constraint(TEST_UNMOD_ZERO, arrayRef, index->var, index->constant);
+ add_new_constraint(TEST_UNMOD_ALENGTH, arrayRef, index->var, index->constant);
+ low = high = 1;
+ }
+
+ /* if the addition of new variable tests made guarantees possible, */
+ /* return the best possible optimization */
+ if ((high > 0) && (low > 0)) {
+ /* printf("fully optimzed\n"); */
+#ifdef STATISTICS
+ c_stat_full_opt++;
+#endif
+ return OPT_FULL;
+ }
+ else if (high > 0) {
+ /* printf("upper optimzed\n"); */
+#ifdef STATISTICS
+ c_stat_upper_opt++;
+#endif
+ return OPT_UPPER;
+ }
+ else if (low > 0) {
+ /* printf("lower optimzed\n"); */
+#ifdef STATISTICS
+ c_stat_lower_opt++;
+#endif
+ return OPT_LOWER;
+ }
+ else {
+ /* printf("not optimzed\n"); */
+#ifdef STATISTICS
+ c_stat_no_opt++;
+#endif
+ return OPT_NONE;
+ }
+ break;
+
+ case TRACE_ICONST: /* if it is a constant, optimization is easy */
+ if (index->constant < 0) {
+#ifdef STATISTICS
+ c_stat_no_opt++;
+#endif
+ return OPT_NONE; /* negative index -> bad */
+ }
+ else {
+ add_new_constraint(TEST_CONST_ALENGTH, arrayRef, 0, index->constant);
+#ifdef STATISTICS
+ c_stat_full_opt++;
+#endif
+ return OPT_FULL; /* else just test constant against array length */
+ }
+ break;
+
+ case TRACE_ALENGTH: /* else, no optimizations possible */
+ case TRACE_UNKNOWN:
+ case TRACE_AVAR:
+#ifdef STATISTICS
+ c_stat_no_opt++;
+#endif
+ return OPT_NONE;
+ }
+}
+
+
+
+/* copy a stack and return the start pointer of the newly created one
+*/
+stackptr copy_stack_from(stackptr source) {
+ stackptr current, top;
+
+ if (source == NULL)
+ return NULL;
+
+ /* copy first element */
+ current = DMNEW(stackelement, 1);
+ current->type = source->type;
+ current->flags = source->flags;
+ current->varkind = source->varkind;
+ current->varnum = source->varnum;
+ current->regoff = source->regoff;
+
+ top = current;
+
+ /* if there exist more, then copy the rest */
+ while (source->prev != NULL) {
+ source = source->prev;
+ current->prev = DMNEW(stackelement, 1);
+ current->type = source->type;
+ current->flags = source->flags;
+ current->varkind = source->varkind;
+ current->varnum = source->varnum;
+ current->regoff = source->regoff;
+ current = current->prev;
+ }
+
+ current->prev = NULL;
+ return top;
+}
+
+
+/* The following defines are used in the procedure void create_static_checks(...)
+ They add a new instruction with its corresponding stack manipulation and
+ are used to build the new loop header of an optimized loop, where we have
+ to check certain variables and constants against values to guarantee that
+ index values in array accesses remain with array bounds.
+
+ inst: pointer to the new instruction
+ tos: stackpointer before this operation is executed
+ newstack: temporary stackptr
+ stackdepth: counts the current stackdepth
+ original start: blockpointer to the head of the new, optimized loop
+*/
+
+/* Load a local integer variable v */
+#define LOAD_VAR(v) { \
+ inst->opc = ICMD_ILOAD; \
+ inst->op1 = v; \
+ newstack = DMNEW(stackelement, 1); \
+ inst->dst = newstack; \
+ newstack->prev = tos; \
+ newstack->type = TYPE_INT; \
+ newstack->flags = 0; \
+ newstack->varkind = LOCALVAR; \
+ newstack->varnum = v; \
+ tos = newstack; \
+ inst++; \
+ stackdepth++; \
+ }
+
+/* Load a constant with value c */
+#define LOAD_CONST(c) { \
+ inst->opc = ICMD_ICONST; \
+ inst->op1 = 0; \
+ inst->val.i = (c); \
+ newstack = DMNEW(stackelement, 1); \
+ newstack->prev = tos; \
+ newstack->type = TYPE_INT; \
+ newstack->flags = 0; \
+ newstack->varkind = UNDEFVAR; \
+ newstack->varnum = stackdepth; \
+ tos = newstack; \
+ inst->dst = tos; \
+ inst++; \
+ stackdepth++; \
+ }
+
+/* Load a local reference (adress) variable a */
+#define LOAD_ADDR(a) { \
+ inst->opc = ICMD_ALOAD; \
+ inst->op1 = a; \
+ newstack = DMNEW(stackelement, 1); \
+ newstack->prev = tos; \
+ newstack->type = TYPE_ADR; \
+ newstack->flags = 0; \
+ newstack->varkind = LOCALVAR; \
+ newstack->varnum = a; \
+ tos = newstack; \
+ inst->dst = tos; \
+ inst++; \
+ stackdepth++; \
+ }
+
+/* Insert a compare greater-or-equal and jump to the unoptimized loop, if the */
+/* comparison is true */
+#define GOTO_NOOPT_IF_GE { \
+ inst->opc = ICMD_IF_ICMPGE; \
+ inst->target = original_start->copied_to; \
+ if (tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ if (tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ inst->dst = tos; \
+ inst++; \
+ stackdepth -= 2; \
+ }
+
+/* Insert a compare greater than and jump to the unoptimized loop, if the */
+/* comparison is true */
+#define GOTO_NOOPT_IF_GT { \
+ inst->opc = ICMD_IF_ICMPGT; \
+ inst->target = original_start->copied_to; \
+ if (tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ if (tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ inst->dst = tos; \
+ inst++; \
+ stackdepth -= 2; \
+ }
+
+
+/* Insert a compare less-than and jump to the unoptimized loop, if the */
+/* comparison is true */
+#define GOTO_NOOPT_IF_LT { \
+ inst->opc = ICMD_IF_ICMPLT; \
+ inst->target = original_start->copied_to; \
+ if(tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ if(tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ inst->dst = tos; \
+ inst++; \
+ stackdepth -= 2; \
+ }
+
+/* Insert a compare if-not-null and jump to the unoptimized loop, if the */
+/* comparison is true */
+#define GOTO_NOOPT_IF_NULL { \
+ inst->opc = ICMD_IFNULL; \
+ inst->target = original_start->copied_to; \
+ if(tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ inst->dst = tos; \
+ inst++; \
+ stackdepth -= 1; \
+ }
+
+/* Insert an add instruction, that adds two integer values on top of the stack */
+/* together */
+#define ADD { \
+ inst->opc = ICMD_IADD; \
+ if(tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ if(tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ newstack = DMNEW(stackelement, 1); \
+ newstack->prev = tos; \
+ newstack->type = TYPE_INT; \
+ newstack->flags = 0; \
+ newstack->varkind = UNDEFVAR; \
+ newstack->varnum = stackdepth; \
+ tos = newstack; \
+ inst->dst = tos; \
+ inst++; \
+ stackdepth--; \
+ }
+
+/* Insert instructions to load the arraylength of an array with reference a */
+/* fisrt, the reference must be loaded, then a null-pointer check is inserted */
+/* if not already done earlier. Finally an arraylength instruction is added */
+#define LOAD_ARRAYLENGTH(a) { \
+ if (c_null_check[a]) { \
+ LOAD_ADDR(a); \
+ GOTO_NOOPT_IF_NULL; \
+ c_null_check[a] = 0; \
+ } \
+ LOAD_ADDR(a); \
+ inst->opc = ICMD_ARRAYLENGTH; \
+ if(tos->varkind == UNDEFVAR) \
+ tos->varkind = TEMPVAR; \
+ tos = tos->prev; \
+ newstack = DMNEW(stackelement, 1); \
+ newstack->prev = tos; \
+ newstack->type = TYPE_INT; \
+ newstack->flags = 0; \
+ newstack->varkind = UNDEFVAR; \
+ newstack->varnum = stackdepth; \
+ tos = newstack; \
+ inst->dst = tos; \
+ inst++; \
+ }
+
+
+/* Inserts the instructions to load the value of the right side of comparison */
+/* Depending of the type of the right side, the apropriate instructions are */
+/* created. */
+#define LOAD_RIGHT_SIDE { \
+ switch (c_rightside->type) { \
+ case TRACE_ICONST: \
+ LOAD_CONST(c_rightside->constant); \
+ break; \
+ case TRACE_IVAR: \
+ LOAD_VAR(c_rightside->var); \
+ LOAD_CONST(c_rightside->constant); \
+ ADD; \
+ break; \
+ case TRACE_ALENGTH: \
+ LOAD_ARRAYLENGTH(c_rightside->var); \
+ break; \
+ default: \
+ printf("C_ERROR: illegal trace on rightside of loop-header\n"); \
+ exit; \
+ } \
+}
+
+/* Patch jumps in original loop and in copied loop, add gotos in copied loop.
+ All jumps in the original loop to the loop head have to be redirected to
+ the newly inserted one. For the copied loop, it is necessay to redirect all
+ jumps inside that loop to the copied nodes. lc points to the current loop,
+ loop_head is a pointer to the newly inserted head and original start was
+ the old head and is now the head of the optimized variant of the loop.
+*/
+void patch_jumps(basicblock *original_start, basicblock *loop_head, struct LoopContainer *lc)
+{
+ /* step through all nodes of a loop */
+ struct LoopElement *le;
+ basicblock *bptr;
+ instruction *inst, *temp_instr;
+ int i;
+
+ le = lc->nodes;
+ while (le != NULL) {
+
+ /* do nothing for new loop head */
+ if (le->block == loop_head) {
+ le = le->next;
+ continue;
+ }
+
+ /* for original version */
+ bptr = le->block;
+ inst = bptr->iinstr;
+ for (i = 0; i < bptr->icount; ++i, ++inst) {
+ switch (inst->opc) {
+
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPGE:
+
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPLE:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPGE:
+
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
+
+ case ICMD_GOTO:
+ case ICMD_JSR:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+
+ /* jump to newly inserted loopheader has to be redirected */
+ if (((basicblock *) inst->target) == loop_head)
+ inst->target = (void *) original_start;
+ break;
+
+ case ICMD_TABLESWITCH:
+ {
+ s4 *s4ptr, l, i;
+ void **tptr;
+
+ tptr = (void **) inst->target;
+
+ s4ptr = inst->val.a;
+ l = s4ptr[1]; /* low */
+ i = s4ptr[2]; /* high */
+
+ i = i - l + 1;
+
+ /* jump to newly inserted loopheader has to be redirected */
+ for (tptr = inst->target; i >= 0; --i, ++tptr) {
+ if (((basicblock *) *tptr) == loop_head)
+ tptr[0] = (void *) original_start;
+ }
+ }
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ {
+ s4 i, l, val, *s4ptr;
+ void **tptr;
+
+ tptr = (void **) inst->target;
+
+ s4ptr = inst->val.a;
+ l = s4ptr[0]; /* default */
+ i = s4ptr[1]; /* count */
+
+ /* jump to newly inserted loopheader has to be redirected */
+ for (tptr = inst->target; i >= 0; --i, ++tptr) {
+ if (((basicblock *) *tptr) == loop_head)
+ tptr[0] = (void *) original_start;
+ }
+ }
+ break;
+
+ }
+ }
+
+ /* if node is part of loop and has fall through to original start, that */
+ /* must be redirected. Unfortunately the instructions have to be copied */
+
+ if (bptr->next == loop_head) {
+ temp_instr = DMNEW(instruction, bptr->icount + 1);
+ memcpy(temp_instr, bptr->iinstr, sizeof(instruction)*bptr->icount);
+ bptr->iinstr = temp_instr;
+
+ bptr->iinstr[bptr->icount].opc = ICMD_GOTO;
+ bptr->iinstr[bptr->icount].target = original_start;
+ bptr->iinstr[bptr->icount].dst = NULL;
+ ++bptr->icount;
+ }
+
+ /* for copied version - which gets the unoptimized variant */
+ bptr = le->block->copied_to;
+ inst = bptr->iinstr;
+ for (i = 0; i < bptr->icount; ++i, ++inst) {
+
+ switch (inst->opc) {
+
+ case ICMD_IASTORE: /* array store */
+ case ICMD_LASTORE:
+ case ICMD_FASTORE:
+ case ICMD_DASTORE:
+ case ICMD_AASTORE:
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_SASTORE:
+ case ICMD_IALOAD: /* array load */
+ case ICMD_LALOAD:
+ case ICMD_FALOAD:
+ case ICMD_DALOAD:
+ case ICMD_AALOAD:
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_SALOAD:
+
+ /* undo previous optimizations in new loop */
+ inst->op1 = 0;
+ break;
+
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPGE:
+
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPLE:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPGE:
+
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
+
+ case ICMD_GOTO:
+ case ICMD_JSR:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+
+ /* jump to newly inserted loopheader has to be redirected */
+ if (((basicblock *) inst->target) == loop_head)
+ inst->target = (void *) original_start->copied_to;
+ /* jump to loop internal nodes has to be redirected */
+ else if (((basicblock *) inst->target)->lflags & LOOP_PART)
+ inst->target = (void *) ((basicblock *) inst->target)->copied_to;
+ break;
+
+ case ICMD_TABLESWITCH:
+ {
+ s4 *s4ptr, l, i;
+
+ void **copy_ptr, *base_ptr;
+ void **tptr;
+
+ tptr = (void **) inst->target;
+
+ s4ptr = inst->val.a;
+ l = s4ptr[1]; /* low */
+ i = s4ptr[2]; /* high */
+
+ i = i - l + 1;
+
+ copy_ptr = (void**) DMNEW(void*, i+1);
+ base_ptr = (void*) copy_ptr;
+
+ /* Targets for switch instructions are stored in an extra */
+ /* that must be copied for new inserted loop. */
+
+ for (tptr = inst->target; i >= 0; --i, ++tptr, ++copy_ptr) {
+ /* jump to newly inserted loopheader must be redirected */
+ if (((basicblock *) *tptr) == loop_head)
+ copy_ptr[0] = (void *) original_start->copied_to;
+ /* jump to loop internal nodes has to be redirected */
+ else if (((basicblock *) *tptr)->lflags & LOOP_PART)
+ copy_ptr[0] = (void *) ((basicblock *) tptr[0])->copied_to;
+ else
+ copy_ptr[0] = tptr[0];
+ }
+
+ inst->target = base_ptr;
+ }
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ {
+ s4 i, l, val, *s4ptr;
+
+ void **copy_ptr, **base_ptr;
+ void **tptr;
+
+ tptr = (void **) inst->target;
+
+ s4ptr = inst->val.a;
+ l = s4ptr[0]; /* default */
+ i = s4ptr[1]; /* count */
+
+ copy_ptr = (void**) DMNEW(void*, i+1);
+ base_ptr = (void*) copy_ptr;
+
+ /* Targets for switch instructions are stored in an extra */
+ /* that must be copied for new inserted loop. */
+
+ for (tptr = inst->target; i >= 0; --i, ++tptr, ++copy_ptr) {
+ /* jump to newly inserted loopheader must be redirected */
+ if (((basicblock *) *tptr) == loop_head)
+ copy_ptr[0] = (void *) original_start->copied_to;
+ /* jump to loop internal nodes has to be redirected */
+ else if (((basicblock *) *tptr)->lflags & LOOP_PART)
+ copy_ptr[0] = (void *) ((basicblock *) tptr[0])->copied_to;
+ else
+ copy_ptr[0] = tptr[0];
+ }
+
+ inst->target = base_ptr;
+ }
+ break;
+
+ }
+ }
+
+ /* if fall through exits loop, goto is needed */
+ if (!(le->block->next->lflags & LOOP_PART)) {
+ bptr->iinstr[bptr->icount].opc = ICMD_GOTO;
+ bptr->iinstr[bptr->icount].dst = NULL;
+ bptr->iinstr[bptr->icount].target = le->block->next;
+ bptr->icount++;
+ }
+
+ le = le->next;
+ }
+}
+
+/* Add the new header node of a loop that has been duplicated to all parent
+ loops in nesting hierarchie.
+*/
+void header_into_parent_loops(struct LoopContainer *lc, basicblock *to_insert, basicblock *replace, basicblock *after)
+{
+ /* we have to insert the node to_insert before the node after and replace */
+ /* the pointer of to_insert by the node replace */
+
+ struct LoopElement *le, *t;
+
+ /* if the top of the tree is reached, then return */
+ if ((lc == NULL) || (lc == root))
+ return;
+
+ /* create new node, that should be inserted */
+ t = DMNEW(struct LoopElement, 1);
+ t->block = to_insert;
+ t->node = -1;
+
+ /* first, find the node, that has to be replaced (= "to_insert") and */
+ /* replace it by the node "replace" */
+ le = lc->nodes;
+ while (le->block != to_insert)
+ le = le->next;
+ le->block = replace;
+
+ /* now find the node after and insert the newly create node before "after" */
+ le = lc->nodes;
+ if (le->block == after) {
+ t->next = lc->nodes;
+ lc->nodes = t;
+ }
+ else {
+ while (le->next->block != after)
+ le = le->next;
+
+ t->next = le->next;
+ le->next = t;
+ }
+
+ /* go up one hierarchie level */
+ header_into_parent_loops(lc->parent, to_insert, replace, after);
+}
+
+/* Add a new node (not header) of a duplicated loop to all parent loops in
+ nesting hierarchie
+*/
+void node_into_parent_loops(struct LoopContainer *lc, basicblock *to_insert)
+{
+ struct LoopElement *le, *t;
+
+ /* if the top of the tree is reached, then return */
+ if ((lc == NULL) || (lc == root))
+ return;
+
+ /* create new node, that should be inserted */
+ t = DMNEW(struct LoopElement, 1);
+ t->block = to_insert;
+ t->node = -1;
+
+ le = lc->nodes;
+
+ /* append new node to node list of loop */
+ while (le->next != NULL)
+ le = le->next;
+
+ t->next = le->next;
+ le->next = t;
+
+ /* go up one hierarchie level */
+ node_into_parent_loops(NULL, to_insert);
+}
+
+
+/* void patch_handler(...) is very similar to parts of the function patch_jumps.
+ Its task is to redirect all jumps from the original head to the new head and
+ to redirect internal jumps inside the exception handler to the newly
+ created (copied) nodes.
+*/
+void patch_handler(struct LoopContainer *lc, basicblock *bptr, basicblock *original_head, basicblock *new_head)
+{
+ instruction *ip;
+ s4 *s4ptr;
+ void **tptr;
+ int high, low, count, i;
+
+ /* If node is not part of exception handler or has been visited, exit */
+ if (!(bptr->lflags & HANDLER_PART) || (bptr->lflags & HANDLER_VISITED))
+ return;
+
+ /* mark block as visited */
+ bptr->lflags |= HANDLER_VISITED;
+
+ /* for all instructions in the copied block, do */
+ for (i = 0, ip = bptr->copied_to->iinstr; i < bptr->copied_to->icount; ++i, ++ip) {
+ switch (ip->opc) {
+ case ICMD_RETURN:
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ case ICMD_ATHROW:
+ break;
+
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPGE:
+
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPLE:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPGE:
+
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
+
+ case ICMD_JSR:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+
+ patch_handler(lc, bptr->next, original_head, new_head);
+
+ /* fall through */
+
+ case ICMD_GOTO:
+
+ patch_handler(lc, ip->target, original_head, new_head);
+
+ /* jumps to old header have to be redirected */
+ if (((basicblock *) ip->target) == original_head)
+ ip->target = (void *) new_head->copied_to;
+ /* jumps to handler internal nodes have to be redirected */
+ else if (((basicblock *) ip->target)->lflags & HANDLER_PART)
+ ip->target = (void *) ((basicblock *) ip->target)->copied_to;
+ /* jumps to loop internal nodes have to be redirected */
+ else if (((basicblock *) ip->target)->lflags & LOOP_PART)
+ ip->target = (void *) ((basicblock *) ip->target)->copied_to;
+
+
+ break;
+
+ case ICMD_TABLESWITCH:
+ {
+ s4 *s4ptr, l, i;
+ void **tptr;
+ void **copy_ptr, **base_ptr;
+
+ tptr = (void **) ip->target;
+ s4ptr = ip->val.a;
+ l = s4ptr[1]; /* low */
+ i = s4ptr[2]; /* high */
+ i = i - l + 1;
+
+ copy_ptr = (void**) DMNEW(void*, i+1);
+ base_ptr = (void*) copy_ptr;
+
+ for (tptr = ip->target; i >= 0; --i, ++tptr, ++copy_ptr) {
+ patch_handler(lc, ((basicblock *) *tptr), original_head, new_head);
+ /* jumps to old header have to be redirected */
+ if (((basicblock *) *tptr) == original_head)
+ copy_ptr[0] = (void *) new_head->copied_to;
+ /* jumps to handler internal nodes have to be redirected */
+ else if (((basicblock *) *tptr)->lflags & HANDLER_PART)
+ copy_ptr[0] = (void *) ((basicblock *) tptr[0])->copied_to;
+ /* jumps to loop internal nodes have to be redirected */
+ else if (((basicblock *) ip->target)->lflags & LOOP_PART)
+ copy_ptr[0] = (void *) ((basicblock *) tptr[0])->copied_to;
+ else
+ copy_ptr[0] = tptr[0];
+ }
+
+ ip->target = base_ptr;
+ }
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ {
+ s4 i, l, val, *s4ptr;
+
+ void **tptr;
+ void **copy_ptr, **base_ptr;
+
+ tptr = (void **) ip->target;
+ s4ptr = ip->val.a;
+ l = s4ptr[0]; /* default */
+ i = s4ptr[1]; /* count */
+
+ copy_ptr = (void**) DMNEW(void*, i+1);
+ base_ptr = (void*) copy_ptr;
+
+ for (tptr = ip->target; i >= 0; --i, ++tptr, ++copy_ptr) {
+
+ patch_handler(lc, ((basicblock *) *tptr), original_head, new_head);
+ /* jumps to old header have to be redirected */
+ if (((basicblock *) *tptr) == original_head)
+ copy_ptr[0] = (void *) new_head->copied_to;
+ /* jumps to handler internal nodes have to be redirected */
+ else if (((basicblock *) *tptr)->lflags & HANDLER_PART)
+ copy_ptr[0] = (void *) ((basicblock *) tptr[0])->copied_to;
+ /* jumps to loop internal nodes have to be redirected */
+ else if (((basicblock *) ip->target)->lflags & LOOP_PART)
+ copy_ptr[0] = (void *) ((basicblock *) tptr[0])->copied_to;
+ else
+ copy_ptr[0] = tptr[0];
+ }
+
+ ip->target = base_ptr;
+ }
+ break;
+
+ } /* switch */
+
+ } /* for */
+
+ /* if fall through exits loop, goto is needed */
+ if (!(bptr->next->lflags & HANDLER_PART)) {
+ bptr->copied_to->iinstr[bptr->copied_to->icount].opc = ICMD_GOTO;
+ bptr->copied_to->iinstr[bptr->copied_to->icount].dst = NULL;
+ bptr->copied_to->iinstr[bptr->copied_to->icount].target = bptr->next;
+ bptr->copied_to->icount++;
+ }
+}
+
+
+/* This function copys the exception handler and redirects all jumps from the
+ original head to the new head in the original exception handler. All
+ redirection in the copied exception handler is done in patch_handler(...).
+*/
+void copy_handler(struct LoopContainer *lc, basicblock *bptr, basicblock *original_head, basicblock *new_head)
+{
+ instruction *ip;
+ s4 *s4ptr;
+ void **tptr;
+ int high, low, count, cnt;
+ struct LoopElement *le;
+ basicblock *new;
+
+ /* If this node has already been copied, return */
+ if (bptr->lflags & HANDLER_PART)
+ return;
+
+ /* The exception handler exists, when control flow enters loop again */
+
+ if (bptr->lflags & LOOP_PART)
+ return;
+ for (le = lc->nodes; le != NULL; le = le->next) {
+ if (le->block == bptr) {
+ printf("C_PANIC: should not happen\n");
+ exit(-1);
+ }
+ }
+
+ /* mark block as part of handler */
+ bptr->lflags |= HANDLER_PART;
+
+ /* copy node */
+ new = DMNEW(basicblock, 1);
+ memcpy(new, bptr, sizeof(basicblock));
+ new->debug_nr = c_debug_nr++;
+
+ c_last_block_copied = new;
+
+ /* copy instructions and allow one more slot for possible GOTO */
+ new->iinstr = DMNEW(instruction, bptr->icount + 1);
+ memcpy(new->iinstr, bptr->iinstr, bptr->icount*sizeof(instruction));
+
+ /* update original block */
+ bptr->copied_to = new;
+
+ /* append block to global list of basic blocks */
+ last_block->next = new;
+ last_block = new;
+ new->next = NULL;
+
+
+ /* find next block to copy, depending on last instruction of BB */
+ if (bptr->icount == 0) {
+ copy_handler(lc, bptr->next, original_head, new_head);
+ return;
+ }
+
+ ip = bptr->iinstr + (bptr->icount - 1);
+
+ switch (ip->opc) {
+ case ICMD_RETURN:
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ case ICMD_ATHROW:
+ break;
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPLE:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPGE:
+
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
+
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ copy_handler(lc, bptr->next, original_head, new_head);
+ /* fall through */
+
+ case ICMD_GOTO:
+
+ /* redirect jump from original_head to new_head */
+ if ((basicblock *) ip->target == original_head)
+ ip->target = (void *) new_head;
+
+ copy_handler(lc, (basicblock *) (ip->target), original_head, new_head);
+
+ break;
+
+ case ICMD_TABLESWITCH:
+ s4ptr = ip->val.a;
+ tptr = (void **) ip->target;
+
+ /* default branch */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
+
+ copy_handler(lc, (basicblock *) *tptr, original_head, new_head);
+
+ s4ptr++;
+ low = *s4ptr;
+ s4ptr++;
+ high = *s4ptr;
+
+ count = (high-low+1);
+
+ while (--count >= 0) {
+ tptr++;
+ /* redirect jump from original_head to new_head */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
+ copy_handler(lc, (basicblock *) *tptr, original_head, new_head);
+ }
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ s4ptr = ip->val.a;
+ tptr = (void **) ip->target;
+
+ /* default branch */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
+
+ copy_handler(lc, (basicblock *) *tptr, original_head, new_head);
+
+ ++s4ptr;
+ count = *s4ptr;
+
+ while (--count >= 0) {
+ ++tptr;
+ /* redirect jump from original_head to new_head */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
+ copy_handler(lc, (basicblock *) *tptr, original_head, new_head);
+ }
+ break;
+
+ case ICMD_JSR:
+ c_last_target = bptr;
+ copy_handler(lc, (basicblock *) (ip->target), original_head, new_head);
+ break;
+
+ case ICMD_RET:
+ copy_handler(lc, c_last_target->next, original_head, new_head);
+ break;
+
+ default:
+ copy_handler(lc, bptr->next, original_head, new_head);
+ break;
+ }
+
+}
+
+
+/* If a loop is duplicated, all exceptions, that are contained in this loops' body
+ have to be duplicated as well. The following function together with the
+ two helper functions copy_handler and patch_handler perform this task.
+*/
+void update_internal_exceptions(struct LoopContainer *lc, basicblock *original_head, basicblock *new_head)
+{
+ xtable *ex, *new;
+ struct LoopContainer *l;
+
+ /* Bottom of tree reached -> return */
+ if (lc == NULL)
+ return;
+
+ /* Call update_internal for all nested (=child) loops */
+ l = lc->tree_down;
+ while (l != NULL) {
+ update_internal_exceptions(l, original_head, new_head);
+ l = l->tree_right;
+ }
+
+ /* For all exceptions of this loop, do */
+ ex = lc->exceptions;
+ while (ex != NULL) {
+
+ /* Copy the exception and patch the jumps */
+ copy_handler(lc, ex->handler, original_head, new_head);
+ patch_handler(lc, ex->handler, original_head, new_head);
+
+ /* Insert a new exception into the global exception table */
+ new = DMNEW(xtable, 1);
+ memcpy(new, ex, sizeof(xtable));
+
+ /* Increase number of exceptions */
+ ++exceptiontablelength;
+
+ ex->next = new;
+ ex->down = new;
+
+ /* Set new start and end point of this exception */
+ new->start = ex->start->copied_to;
+ new->end = ex->end->copied_to;
+
+ /* Set handler pointer to copied exception handler */
+ new->handler = ex->handler->copied_to;
+
+ ex = new->next;
+ }
+
+}
+
+/* If a loop is duplicated, all exceptions that contain this loop have to be
+ extended to the copied nodes as well. The following function checks for
+ all exceptions of all parent loops, whether they contain the loop pointed to
+ by lc. If so, the exceptions are extended to contain all newly created nodes.
+*/
+void update_external_exceptions(struct LoopContainer *lc, int loop_head)
+{
+ xtable *ex, *new;
+
+ /* Top of tree reached -> return */
+ if (lc == NULL)
+ return;
+
+ ex = lc->exceptions;
+
+ /* For all exceptions of this loop do */
+ while (ex != NULL) {
+
+ /* It is possible that the loop contains exceptions that do not protect */
+ /* the loop just duplicated. It must be checked, if this is the case */
+ if ((loop_head >= block_index[ex->startpc]) && (loop_head < block_index[ex->endpc])) {
+
+ /* loop is really inside exception, so create new exception entry */
+ /* in global exception list */
+ new = DMNEW(xtable, 1);
+ memcpy(new, ex, sizeof(xtable));
+
+
+ /* Increase number of exceptions */
+ ++exceptiontablelength;
+
+ ex->next = new;
+ ex->down = new;
+
+ /* Set new start and end point of this exception */
+ new->start = c_first_block_copied;
+ new->end = c_last_block_copied;
+
+ ex = new->next;
+ }
+ /* exception does not contain the duplicated loop -> do nothing */
+ else
+ ex = ex->next;
+ }
+
+ /* Call update_external for parent node */
+ update_external_exceptions(lc->parent, loop_head);
+}
+
+
+
+/* This function is needed to insert the static checks, stored in c_constraints
+ into the intermediate code.
+*/
+void create_static_checks(struct LoopContainer *lc)
+{
+ int i, j, stackdepth, cnt;
+ struct Changes **c;
+ struct Constraint *tc1, *tc2;
+ struct LoopElement *le;
+
+ /* loop_head points to the newly inserted loop_head, original_start to */
+ /* the old loop header */
+ basicblock *bptr, *loop_head, *original_start, *temp;
+ instruction *inst, *tiptr;
+
+ /* tos and newstack are needed by the macros, that insert instructions into */
+ /* the new loop head */
+ stackptr newstack, tos, sptr;
+ xtable *ex;
+
+#ifdef STATISTICS
+ /* show_loop_statistics(); */
+#endif
+
+ loop_head = &block[c_current_head];
+ c_first_block_copied = c_last_block_copied = NULL;
+
+ /* the loop nodes are copied */
+ le = lc->nodes;
+ while (le != NULL)
+ {
+ bptr = DMNEW(basicblock, 1);
+ memcpy(bptr, le->block, sizeof(basicblock));
+ bptr->debug_nr = c_debug_nr++;
+
+ /* determine beginning of copied loop to extend exception handler, that */
+ /* protect this loop */
+ if (c_first_block_copied == NULL)
+ c_first_block_copied = bptr;
+
+ /* copy instructions and add one more slot for possible GOTO */
+ bptr->iinstr = DMNEW(instruction, bptr->icount + 1);
+
+ memcpy(bptr->iinstr, le->block->iinstr, (bptr->icount+1)*sizeof(instruction));
+
+ le->block->copied_to = bptr;
+
+ /* add block to global list of BBs */
+ last_block->next = bptr;
+ last_block = bptr;
+ bptr->next = NULL;
+
+ node_into_parent_loops(lc->parent, bptr);
+ le = le->next;
+ }
+
+ c_last_block_copied = bptr;
+
+ /* create an additional basicblock for dynamic checks */
+ original_start = bptr = DMNEW(basicblock, 1);
+
+ /* copy current loop header to new basic block */
+ memcpy(bptr, loop_head, sizeof(basicblock));
+ bptr->debug_nr = c_debug_nr++;
+
+ /* insert the new basic block and move header before first loop node */
+ le = lc->nodes;
+ temp = le->block;
+
+ /* if header is first node of loop, insert original header after it */
+ if (temp == loop_head)
+ loop_head->next = bptr;
+ else {
+ /* else, we have to find the predecessor of loop header */
+ while (temp->next != loop_head)
+ temp = temp->next;
+
+ /* insert original header after newly created block */
+ temp->next = bptr;
+
+ /* if predecessor is not loop part, insert a goto */
+ if (!(temp->lflags & LOOP_PART)) {
+
+ /* copy instructions and add an additional slot */
+ tiptr = DMNEW(instruction, temp->icount + 1);
+ memcpy(tiptr, temp->iinstr, sizeof(instruction)*temp->icount);
+
+ temp->iinstr = tiptr;
+ tiptr = temp->iinstr + temp->icount;
+
+ /* add goto to loop header. If node is part of exception handler */
+ /* jmp is automagically redirected during patch_handler and works */
+ /* correct */
+ tiptr->opc = ICMD_GOTO;
+ tiptr->dst = NULL;
+ tiptr->target = (void*) loop_head;
+
+ ++temp->icount;
+ }
+
+
+ temp = block;
+ /* if first loop block is first BB of global list, insert loop_head at */
+ /* beginning of global BB list */
+ if (temp == le->block) {
+ if (c_newstart == NULL) {
+ c_needs_redirection = true;
+ c_newstart = loop_head;
+ loop_head->next = block;
+ }
+ else {
+ loop_head->next = c_newstart;
+ c_newstart = loop_head;
+ }
+ }
+ else {
+
+ while (temp->next != le->block)
+ temp = temp->next;
+
+ loop_head->next = temp->next;
+ temp->next = loop_head;
+
+ /* to be on the safe side insert a jump from the previous instr */
+ /* over thr new inserted node */
+
+ /* special case - jump from node to loop_head: then remove */
+ /* goto / happens rather often due to loop layout */
+ tiptr = temp->iinstr + (temp->icount-1);
+
+ if ((tiptr->opc == ICMD_GOTO) && (tiptr->target == loop_head)) {
+ tiptr->opc = ICMD_NOP;
+ tiptr->dst = NULL;
+ }
+ else {
+
+ tiptr = DMNEW(instruction, temp->icount + 1);
+ memcpy(tiptr, temp->iinstr, sizeof(instruction)*temp->icount);
+
+ temp->iinstr = tiptr;
+ tiptr = temp->iinstr + temp->icount;
+
+ tiptr->opc = ICMD_GOTO;
+ tiptr->dst = NULL;
+ tiptr->target = (void*) loop_head->next;
+
+ ++temp->icount;
+ }
+ }
+ }
+
+ /* adjust exceptions */
+ ex = extable;
+ while (ex != NULL) {
+
+ /* if an exception covers whole loop and starts at first loop node, it */
+ /* has to be extended to cover the new first node as well */
+ if (ex->start == le->block) {
+
+ if ((lc->loop_head >= block_index[ex->startpc]) && (lc->loop_head < block_index[ex->endpc]))
+ ex->start = loop_head;
+ }
+
+ /* an exception that ended at the old loop header now must contains the */
+ /* new loop header as well */
+ if (ex->end == loop_head)
+ ex->end = original_start;
+
+ ex = ex->down;
+ }
+
+
+ /* insert new header node into nodelists of all enclosing loops */
+ header_into_parent_loops(lc, loop_head, original_start, le->block);
+
+ /* prepare instruction array to insert checks */
+ inst = loop_head->iinstr = DMNEW(instruction, c_needed_instr + 2);
+ loop_head->icount = c_needed_instr + 1;
+
+ /* init instruction array */
+ for (cnt=0; cnt<c_needed_instr + 1; ++cnt) {
+ inst[0].opc = ICMD_NOP;
+ inst[0].dst = NULL;
+ }
+
+ loop_head->copied_to = NULL;
+
+ /* prepare stack */
+ loop_head->instack = copy_stack_from(bptr->instack);
+ loop_head->outstack = copy_stack_from(bptr->instack);
+
+ tos = loop_head->instack;
+ stackdepth = loop_head->indepth;
+
+ /* step through all inserted checks and create instructions for them */
+ for (i=0; i<maxlocals+1; ++i)
+ {
+ tc1 = c_constraints[i];
+ while (tc1 != NULL)
+ {
+ switch (tc1->type)
+ {
+
+ /* check a variable against a constant */
+ case TEST_ZERO:
+ case TEST_UNMOD_ZERO:
+
+#ifdef LOOP_DEBUG
+ printf("insert ZERO-test\n");
+ fflush(stdout);
+#endif
+
+ /* optimize if tc1->varRef >= tc1->constant */
+ LOAD_VAR(tc1->varRef);
+ LOAD_CONST(tc1->constant);
+ GOTO_NOOPT_IF_LT;
+ break;
+
+ /* check a variable against an array length */
+ case TEST_ALENGTH:
+ case TEST_UNMOD_ALENGTH:
+
+ /* optimize if */
+ /* tc1->varRef + tc1->constant < lengthOf(tc1->arrayRef) */
+#ifdef LOOP_DEBUG
+ printf("insert ALENGTH-test\n");
+ fflush(stdout);
+#endif
+
+ LOAD_VAR(tc1->varRef);
+ LOAD_CONST(tc1->constant);
+ ADD;
+ LOAD_ARRAYLENGTH(tc1->arrayRef);
+ GOTO_NOOPT_IF_GE;
+ break;
+
+ /* test right side of comparison against constant */
+ case TEST_RS_ZERO:
+
+#ifdef LOOP_DEBUG
+ printf("insert RS-ZERO-test\n");
+ fflush(stdout);
+#endif
+
+ /* optimize if right-side >= tc1->constant */
+ LOAD_RIGHT_SIDE;
+ LOAD_CONST(tc1->constant);
+ GOTO_NOOPT_IF_LT;
+ break;
+
+ /* test right side of comparison against array length */
+ case TEST_RS_ALENGTH:
+
+#ifdef LOOP_DEBUG
+ printf("insert RS-ALENGTH-test\n");
+ fflush(stdout);
+#endif
+ /* optimize if right-side < lengthOf(arrayRef) */
+ LOAD_RIGHT_SIDE;
+ LOAD_ARRAYLENGTH(tc1->arrayRef);
+ GOTO_NOOPT_IF_GT;
+ break;
+
+ /* test unmodified variable against arraylength */
+ case TEST_CONST_ALENGTH:
+
+#ifdef LOOP_DEBUG
+ printf("insert CONST ALENGTH-test\n");
+ fflush(stdout);
+#endif
+
+ /* optimize if tc1->constant < lengthOf(tc1->arrayRef) */
+ LOAD_CONST(tc1->constant);
+ LOAD_ARRAYLENGTH(tc1->arrayRef);
+ GOTO_NOOPT_IF_GE;
+ break;
+ }
+
+ tc1 = tc1->next;
+ }
+ c_constraints[i] = NULL;
+ }
+
+ /* if all tests succeed, jump to optimized loop header */
+ if (loop_head->next != original_start) {
+ inst->opc = ICMD_GOTO;
+ inst->dst = NULL;
+ inst->target = original_start;
+ }
+
+ /* redirect jumps from original loop head to newly inserted one */
+ patch_jumps(original_start, loop_head, lc);
+
+ /* if exceptions have to be correct due to loop duplication these two */
+ /* functions perform this task. */
+ update_internal_exceptions(lc, loop_head, original_start);
+ update_external_exceptions(lc->parent, lc->loop_head);
+
+}
+
+
+/* This function performs an update between two arrays of struct Changes (that
+ reflect variable changes). The merge is performed unrstricted in the way, that
+ all variable changes in c1 took place in a nested loop and therefore are
+ considered to be without limit. Beside that, the merge is a simple union of the
+ changes recorded in both arrays. A variable, which limits are undefinied, is
+ represented by its lower bound being higher than the upper bound. The result
+ of the union is stored in c1.
+*/
+struct Changes ** constraints_unrestricted_merge(struct Changes **c1, struct Changes **c2)
+{
+ int i, changed;
+
+ if ((c1 == NULL) || (c2 == NULL))
+ printf("C_ERROR: debugging error 0x03\n");
+
+ changed = 0;
+ for (i=0; i<maxlocals; ++i) {
+ if (c1[i] == NULL) {
+ if (c2[i] != NULL) { /* a change in c2 is updated in c1 */
+ changed = 1;
+ c1[i] = c2[i];
+ c1[i]->lower_bound = c1[i]->upper_bound+1;
+ }
+ }
+ else {
+ if (c1[i]->lower_bound > c1[i]->upper_bound)
+ continue; /* variable's bounds already undefined */
+
+ if (c2[i] == NULL) { /* variable changed in c1 -> now undef. */
+ changed = 1;
+ c1[i]->lower_bound = c1[i]->upper_bound+1;
+ }
+ else {
+ if ((c1[i]->lower_bound == c2[i]->lower_bound) &&
+ (c1[i]->upper_bound == c2[i]->upper_bound))
+ continue; /* variable's bounds remain the same */
+ else {
+ changed = 1;
+ c1[i]->lower_bound = c1[i]->upper_bound+1;
+ } /* variable changed in c1 -> now undef. */
+ }
+ }
+ }
+
+ if (changed)
+ return c1;
+ else
+ return NULL;
+}
+
+/* This function performs an update between two arrays of struct Changes (that
+ reflect variable changes). The merge is a simple union of the bounds
+ changes recorded in both arrays. A variable, which limits are undefinied, is
+ represented by its lower bound being higher than the upper bound. The result
+ of the union is stored in c1.
+*/
+struct Changes ** constraints_merge(struct Changes **c1, struct Changes **c2)
+{
+ int i, changed;
+
+ if ((c1 == NULL) || (c2 == NULL))
+ printf("C_ERROR: debugging error 0x04\n");
+
+ changed = 0;
+
+ for (i=0; i<maxlocals; ++i) {
+ if (c1[i] == NULL) {
+ if (c2[i] != NULL) { /* update changes in c2 in c1 */
+ if ((c1[i] = (struct Changes *) malloc (sizeof(struct Changes))) == NULL)
+ c_mem_error();
+
+ c1[i]->lower_bound = c2[i]->lower_bound;
+ c1[i]->upper_bound = c2[i]->upper_bound;
+ changed = 1;
+ }
+ }
+ else {
+ if (c2[i] != NULL) {
+
+ if (c1[i]->lower_bound > c1[i]->upper_bound)
+ continue; /* var in c1 is unrestricted */
+
+ if (c1[i]->lower_bound > c2[i]->lower_bound) {
+ c1[i]->lower_bound = c2[i]->lower_bound;
+ changed = 1; /* write new lower bound */
+ }
+ if (c1[i]->upper_bound < c2[i]->upper_bound) {
+ c1[i]->upper_bound = c2[i]->upper_bound;
+ changed = 1; /* write new higher bound */
+ }
+ }
+ }
+ }
+
+ if (changed)
+ return c1;
+ else
+ return NULL;
+}
+
+
+/* This function simply copies an array of changes
+*/
+struct Changes** constraints_clone(struct Changes **c)
+{
+ int i;
+ struct Changes **t;
+
+ if ((t = (struct Changes **) malloc(maxlocals * sizeof(struct Changes *))) == NULL)
+ c_mem_error();
+
+ for (i=0; i<maxlocals; ++i) { /* for all array elements (vars) do */
+ if (c[i] == NULL)
+ t[i] = NULL;
+ else {
+ if ((t[i] = (struct Changes *) malloc(sizeof(struct Changes))) == NULL)
+ c_mem_error();
+ t[i]->lower_bound = c[i]->lower_bound;
+ t[i]->upper_bound = c[i]->upper_bound;
+ }
+ }
+
+ return t;
+}
+
+/* This function is used to reset the changes of a variable to the time, it was
+ pushed onto the stack. If a variable has been modified between an instruction
+ and a previous push onto the stack, its value in the changes array does not
+ correctly reflect its bounds the time, it was pushed onto the stack. This
+ function corrects the situation.
+ */
+struct Changes* backtrack_var(int node, int from, int to, int varRef, struct Changes *changes)
+{
+ struct Changes *tmp;
+ basicblock bp;
+ instruction *ip;
+ struct Trace *t;
+
+ if (changes == NULL) /* if there are no changes, immediately return */
+ return NULL;
+ else { /* init a Changes structure with current values */
+ if ((tmp = (struct Changes *) malloc(sizeof(struct Changes))) == NULL)
+ c_mem_error();
+
+ tmp->upper_bound = changes->upper_bound;
+ tmp->lower_bound = changes->lower_bound;
+ }
+
+ if (tmp->upper_bound < tmp->lower_bound)
+ return tmp; /* if it is unrestricted no backtracking can happen */
+
+ bp = block[node];
+ ip = bp.iinstr + to;
+
+ for (; from < to; --to, --ip) { /* scan instructions backwards */
+ switch (ip->opc) {
+ case ICMD_IINC: /* a var has been modified */
+ if (varRef != ip->op1) /* not the one, we are interested in */
+ break;
+ tmp->upper_bound -= ip->val.i; /* take back modifications */
+ tmp->lower_bound -= ip->val.i;
+ break;
+
+ case ICMD_ISTORE: /* a var has been modified */
+ if (varRef != ip->op1) /* not the one, we are interested in */
+ break;
+
+ /* it is our variable, so trace its origin */
+ t = tracing(&block[node],to, 0);
+
+ switch (t->type) {
+ case TRACE_IVAR:
+ if ((t->var = ip->op1) && (t->neg > 0)) {
+ /* it was the same var -> take back modifications */
+ tmp->upper_bound -= t->constant;
+ tmp->lower_bound -= t->constant;
+ }
+ else
+ tmp->lower_bound = tmp->upper_bound+1; /* unknown */
+ break;
+
+ /* cannot restore it -> invalidate t */
+ case TRACE_ICONST:
+ case TRACE_ALENGTH:
+ case TRACE_UNKNOWN:
+ case TRACE_AVAR:
+ tmp->lower_bound = tmp->upper_bound+1;
+ break;
+ }
+
+ break;
+ }
+ }
+ return tmp;
+}
+
+/* This function performs the main task of bound check removal. It removes
+ all bound-checks in node. change is a pointer to an array of struct Changes
+ that reflect for all local variables, how their values have changed from
+ the start of the loop. The special flag is needed to deal with the header
+ node.
+*/
+void remove_boundchecks(int node, int from, struct Changes **change, int special)
+{
+ basicblock bp;
+ instruction *ip;
+ int i, j, count, ignore, degrade_checks, opt_level;
+ struct depthElement *d;
+ struct Changes **t1, **t2, **tmp, *t;
+ struct Trace *t_array, *t_index;
+
+ /* printf("remove_bc called: %d - %d - %d\n", node, from, special); */
+
+ /* a flag, that is set, when previous optimzations have to be taken back */
+ degrade_checks = 0;
+
+ if (c_current_loop[node] > 0) { /* this node is part of the loop */
+ if (c_current_loop[node] > 1) { /* it is not the header node */
+
+ /* get variable changes, already recorded for this node */
+ t1 = c_dTable[node]->changes;
+
+ if (t1 != NULL) { /* it is not the first visit */
+ if ((c_nestedLoops[node] != c_current_head) && (c_nestedLoops[node] == c_nestedLoops[from])) {
+ /* we are looping in a nested loop, so made optimizations */
+ /* need to be reconsidered */
+ degrade_checks = 1;
+ if (constraints_unrestricted_merge(t1, change) == NULL)
+ return; /* no changes since previous visit */
+ /* if there have been changes, they are updated by */
+ /* constraints_unrestricted_merge in t1 */
+ }
+ else {
+ if (constraints_merge(t1, change) == NULL)
+ return; /* no changes since previous visit */
+ /* if there have been changes, they are updated by */
+ /* constraints_merge in t1 */
+ }
+ }
+ else { /* first visit */
+ /* printf("first visit - constraints cloned\n"); */
+ c_dTable[node]->changes = constraints_clone(change);
+ }
+
+ /* tmp now holds a copy of the updated variable changes */
+ tmp = constraints_clone(c_dTable[node]->changes);
+ }
+ else if (special) { /* header and need special traetment */
+ /* printf("special treatment called\n"); */
+ /* tmp now holds a copy of the current new variable changes */
+ tmp = constraints_clone(change);
+ }
+ else
+ return;
+
+ bp = block[node]; /* scan all instructions */
+ count = bp.icount;
+ ip = bp.iinstr;
+ ignore = 0;
+
+ for (i=0; i<count; ++i, ++ip) {
+ switch (ip->opc) {
+ case ICMD_IASTORE: /* found an array store */
+ case ICMD_LASTORE:
+ case ICMD_FASTORE:
+ case ICMD_DASTORE:
+ case ICMD_AASTORE:
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_SASTORE:
+
+ t_index = tracing(&bp, i-1, 1); /* get index */
+ t_array = tracing(&bp, i-1, 2); /* get array refernce */
+ ignore = 1;
+ /* fall through */
+
+ case ICMD_IALOAD: /* found an array load */
+ case ICMD_LALOAD:
+ case ICMD_FALOAD:
+ case ICMD_DALOAD:
+ case ICMD_AALOAD:
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_SALOAD:
+ if (!ignore) {
+ t_index = tracing(&bp, i-1, 0); /* get index */
+ t_array = tracing(&bp, i-1, 1); /* get array refernce */
+ ignore = 0;
+ }
+
+ /* printf("Array access with params:\n");
+ printf("Array:\n");
+ show_trace(t_array);
+ printf("Index:\n");
+ show_trace(t_index);
+ */
+
+#ifdef STATISTICS
+ if (ip->op1 == OPT_UNCHECKED) { /* found new access */
+ c_stat_array_accesses++;
+ ip->op1 = OPT_NONE;
+ c_stat_no_opt++;
+ }
+#endif
+
+ /* can only optimize known arrays that do not change */
+ if ((t_array->type != TRACE_AVAR) || (c_var_modified[t_array->var]))
+ break;
+
+ switch (t_index->type) { /* now we look at the index */
+ case TRACE_ICONST: /* it is a constant value or an */
+ case TRACE_ALENGTH: /* array length */
+#ifdef STATISTICS
+ switch (ip->op1) { /* take back old optimzation */
+ case OPT_UNCHECKED:
+ break;
+ case OPT_NONE:
+ c_stat_no_opt--;
+ break;
+ case OPT_FULL:
+ c_stat_full_opt--;
+ break;
+ case OPT_UPPER:
+ c_stat_upper_opt--;
+ break;
+ case OPT_LOWER:
+ c_stat_lower_opt--;
+ break;
+ }
+#endif
+ if (degrade_checks) /* replace existing optimization */
+ ip->op1 = insert_static(t_array->var, t_index, NULL, special);
+ else {
+ /* Check current optimization and try to improve it by */
+ /* inserting new checks */
+ switch (ip->op1) {
+ case OPT_UNCHECKED:
+ ip->op1 = insert_static(t_array->var, t_index, NULL, special);
+ break;
+ case OPT_NONE:
+ ip->op1 = insert_static(t_array->var, t_index, NULL, special);
+ break;
+ case OPT_UPPER:
+ opt_level = insert_static(t_array->var, t_index, NULL, special);
+ if ((opt_level == OPT_FULL) || (opt_level == OPT_LOWER))
+ ip->op1 = OPT_FULL;
+ break;
+ case OPT_LOWER:
+ opt_level = insert_static(t_array->var, t_index, NULL, special);
+ if ((opt_level == OPT_FULL) || (opt_level == OPT_UPPER))
+ ip->op1 = OPT_FULL;
+ break;
+ case OPT_FULL:
+#ifdef STATISTICS
+ c_stat_full_opt++;
+#endif
+ break;
+ }
+ }
+ break;
+
+ case TRACE_IVAR: /* it's a variable */
+
+ /* if the variable is changed between its usage as an index */
+ /* of the array access and its push onto the stack, we have */
+ /* to set the changes back to the time, it is pushed onto */
+ /* the stack as an index variable. */
+ t = backtrack_var(node, t_index->nr, i-1, t_index->var, tmp[t_index->var]);
+#ifdef STATISTICS
+ switch (ip->op1) { /* take back old optimzation */
+ case OPT_UNCHECKED:
+ break;
+ case OPT_NONE:
+ c_stat_no_opt--;
+ break;
+ case OPT_FULL:
+ c_stat_full_opt--;
+ break;
+ case OPT_UPPER:
+ c_stat_upper_opt--;
+ break;
+ case OPT_LOWER:
+ c_stat_lower_opt--;
+ break;
+ }
+#endif
+ if (degrade_checks)
+ ip->op1 = insert_static(t_array->var, t_index, t, special);
+ else {
+ /* Check current optimization and try to improve it by */
+ /* insert new check. t reflects var changes for index */
+ switch (ip->op1) {
+ case OPT_UNCHECKED:
+ ip->op1 = insert_static(t_array->var, t_index, t, special);
+ break;
+ case OPT_NONE:
+ ip->op1 = insert_static(t_array->var, t_index, t, special);
+ break;
+ case OPT_UPPER:
+ opt_level = insert_static(t_array->var, t_index, t, special);
+ if ((opt_level == OPT_FULL) || (opt_level == OPT_LOWER))
+ ip->op1 = OPT_FULL;
+ break;
+ case OPT_LOWER:
+ opt_level = insert_static(t_array->var, t_index, t, special);
+ if ((opt_level == OPT_FULL) || (opt_level == OPT_UPPER))
+ ip->op1 = OPT_FULL;
+ break;
+ case OPT_FULL:
+#ifdef STATISTICS
+ c_stat_full_opt++;
+#endif
+ break;
+ }
+ }
+ break;
+
+ case TRACE_UNKNOWN:
+ case TRACE_AVAR:
+ break;
+ }
+ break;
+
+ case ICMD_ISTORE: /* an integer value is stored */
+ t_index = tracing(&bp, i-1, 0); /* trace back its origin */
+
+ /* the struct Changes for this variable needs to be updated */
+ t = tmp[ip->op1];
+ if (t == NULL) { /* if it's the first one, create new entry */
+ if ((t = (struct Changes *) malloc(sizeof(struct Changes))) == NULL)
+ c_mem_error();
+ t->upper_bound = t->lower_bound = 0;
+ tmp[ip->op1] = t;
+ }
+
+ switch (t_index->type) { /* check origin of store */
+
+ case TRACE_ICONST: /* constant -> set bounds to const value */
+ t->upper_bound = t->lower_bound = t_index->constant;
+ break;
+
+ case TRACE_IVAR: /* if it's the same variable, update consts */
+ if ((t_index->var = ip->op1) && (t_index->neg > 0)) {
+ t->upper_bound += t_index->constant;
+ t->lower_bound += t_index->constant;
+ }
+ else
+ t->lower_bound = t->upper_bound+1;
+ break;
+
+ case TRACE_ALENGTH: /* else -> unknown */
+ case TRACE_UNKNOWN:
+ case TRACE_AVAR:
+ t->lower_bound = t->upper_bound+1;
+ break;
+ }
+
+ break;
+
+ case ICMD_IINC:
+
+ /* the struct Changes for this variable needs to be updated */
+ if ((t = tmp[ip->op1]) == NULL) { /* first one -> create new */
+ if ((t = (struct Changes *) malloc(sizeof(struct Changes))) == NULL)
+ c_mem_error();
+ t->upper_bound = t->lower_bound = ip->val.i;
+ tmp[ip->op1] = t;
+ }
+ else { /* update changes, made by iinc */
+ t->upper_bound += ip->val.i;
+ t->lower_bound += ip->val.i;
+ }
+ break;
+ } /* switch */
+ } /* for */
+
+ if (!special) { /* we are not interested in only the header */
+ d = c_dTable[node];
+ while (d != NULL) { /* check all sucessors of current node */
+ remove_boundchecks(d->value, node, tmp, special);
+ d = d->next;
+ }
+ }
+ } /* if */
+}
+
+/* This function calls the bound-check removal function for the header node
+ with a special flag. It is important to notice, that no dynamic
+ constraint hold in the header node (because the comparison is done at
+ block end).
+*/
+void remove_header_boundchecks(int node, struct Changes **changes)
+{
+ remove_boundchecks(node, -1, changes, BOUNDCHECK_SPECIAL);
+}
+
+/* Marks all basicblocks that are part of the loop
+*/
+void mark_loop_nodes(struct LoopContainer *lc)
+{
+ struct LoopElement *le = lc->nodes;
+
+ while (le != NULL) {
+ le->block->lflags |= LOOP_PART;
+ le = le->next;
+ }
+}
+
+/* Clears mark for all basicblocks that are part of the loop
+*/
+void unmark_loop_nodes(struct LoopContainer *lc)
+{
+ struct LoopElement *le = lc->nodes;
+
+ while (le != NULL) {
+ le->block->lflags = 0;
+ le = le->next;
+ }
+}
+
+
+/* This function performs the analysis of code in detected loops and trys to
+ identify array accesses suitable for optimization (bound check removal). The
+ intermediate code is then modified to reflect these optimizations.
+*/
+void optimize_single_loop(struct LoopContainer *lc)
+{
+ struct LoopElement *le;
+ struct depthElement *d;
+ int i, head, node;
+ struct Changes **changes;
+
+ if ((changes = (struct Changes **) malloc(maxlocals * sizeof(struct Changes *))) == NULL)
+ c_mem_error();
+
+ head = c_current_head = lc->loop_head;
+ c_needed_instr = c_rs_needed_instr = 0;
+
+ /* init array for null ptr checks */
+ for (i=0; i<maxlocals; ++i)
+ c_null_check[i] = 0;
+
+
+ /* don't optimize root node (it is the main procedure, not a loop) */
+ if (head < 0)
+ return;
+
+ /* setup variables with initial values */
+ c_loopvars = NULL;
+ for (i=0; i < block_count; ++i) {
+ c_toVisit[i] = 0;
+ c_current_loop[i] = -1;
+ if ((d = c_dTable[i]) != NULL)
+ d->changes = NULL;
+ }
+
+ for (i=0; i < maxlocals; ++i) {
+ c_var_modified[i] = 0;
+ if (changes[i] != NULL) {
+ changes[i] = NULL;
+ printf("C_PANIC 1\n");
+ }
+ }
+
+ for (i=0; i < (maxlocals+1); ++i) {
+ if (c_constraints[i] != NULL) {
+ c_constraints[i] = NULL;
+ printf("C_PANIC 2\n");
+ }
+ }
+
+ le = lc->nodes;
+ while (le != NULL) {
+ node = le->node;
+
+ if (node == head)
+ c_current_loop[node] = 1; /* the header node gets 1 */
+ else if (c_nestedLoops[node] == head)
+ c_current_loop[node] = 2; /* top level nodes get 2 */
+ else
+ c_current_loop[node] = 3; /* nodes, part of nested loop get 3 */
+
+ c_toVisit[node] = 1;
+ le = le->next;
+ }
+
+ /* After setup work has been performed, start to analyse */
+#ifdef LOOP_DEBUG
+ printf("****** Starting analysis (%d)******\n", head);
+ fflush(stdout);
+#endif
+
+ if (analyze_for_array_access(head) > 0) {/* loop contains array access */
+
+#ifdef LOOP_DEBUG
+ printf("analyze for array access finished and found\n");
+ fflush(stdout);
+#endif
+
+ /* for performance reasons the list of all interesting loop vars is */
+ /* scaned and for all modified vars a flag in c_var_modified is set */
+ scan_global_list();
+
+#ifdef LOOP_DEBUG
+ printf("global list scanned\n");
+ fflush(stdout);
+#endif
+
+ /* if the loop header contains or-conditions or an index variable */
+ /* is modified in the catch-block within the loop, a conservative */
+ /* approach is taken and optimizations are cancelled */
+ if (analyze_or_exceptions(head, lc) > 0) {
+
+#ifdef LOOP_DEBUG
+ printf("Analyzed for or/exception - no problems \n");
+ fflsuh(stdout);
+#endif
+
+ init_constraints(head); /* analyze dynamic bounds in header */
+ /* show_right_side(); */
+
+ if (c_rightside == NULL)
+ return;
+
+ /* single pass bound check removal - for all successors, do */
+ remove_header_boundchecks(head, changes);
+
+ d = c_dTable[head];
+ while (d != NULL) {
+ remove_boundchecks(d->value, -1, changes, BOUNDCHECK_REGULAR);
+ d = d->next;
+ }
+
+#ifdef LOOP_DEBUG
+ printf("Array-bound checks finished\n");
+ fflsuh(stdout);
+#endif
+
+ mark_loop_nodes(lc);
+
+#ifdef LOOP_DEBUG
+ printf("START: create static checks\n");
+ fflush(stdout);
+#endif
+
+ create_static_checks(lc); /* create checks */
+
+#ifdef LOOP_DEBUG
+ printf("END: create static checks\n");
+ fflush(stdout);
+#endif
+ unmark_loop_nodes(lc);
+ }
+ }
+ /* else
+ printf("No array accesses found\n"); */
+
+#ifdef STATISTICS
+ c_stat_num_loops++; /* increase number of loops */
+
+ c_stat_sum_accesses += c_stat_array_accesses;
+ c_stat_sum_full += c_stat_full_opt;
+ c_stat_sum_no += c_stat_no_opt;
+ c_stat_sum_lower += c_stat_lower_opt;
+ c_stat_sum_upper += c_stat_upper_opt;
+ c_stat_sum_or += c_stat_or;
+ c_stat_sum_exception += c_stat_exception;
+
+ c_stat_array_accesses = 0;
+ c_stat_full_opt = 0;
+ c_stat_no_opt = 0;
+ c_stat_lower_opt = 0;
+ c_stat_upper_opt = 0;
+ c_stat_or = c_stat_exception = 0;
+#endif
+
+}
+
+/* This function preforms necessary setup work, before the recursive function
+ optimize_single loop can be called.
+*/
+void optimize_loops()
+{
+ struct LoopContainer *lc = c_allLoops;
+
+ /* first, merge loops with same header node - all loops with the same */
+ /* header node are optimizied in one pass, because they all depend on the */
+ /* same dynamic loop condition */
+
+#ifdef LOOP_DEBUG
+ printf("start analyze_double_headers\n");
+ fflush(stdout);
+#endif
+
+ analyze_double_headers();
+
+ /* create array with loop nesting levels - nested loops cause problems, */
+ /* especially, when they modify index variables used in surrounding loops */
+ /* store results in array c_nestedLoops and c_hierarchie */
+
+#ifdef LOOP_DEBUG
+ printf("double done\n");
+ fflush(stdout);
+#endif
+
+ analyze_nested();
+
+#ifdef LOOP_DEBUG
+ printf("analyze nested done\n");
+ fflush(stdout);
+#endif
+
+ /* create array with entries for current loop */
+ c_current_loop = DMNEW(int, block_count);
+ c_toVisit = DMNEW(int, block_count);
+ c_var_modified = DMNEW(int, maxlocals);
+ c_null_check = DMNEW(int, maxlocals);
+
+ if ((c_constraints = (struct Constraint **) malloc((maxlocals+1) * sizeof(struct Constraint *))) == NULL)
+ c_mem_error();
+
+#ifdef STATISTICS
+ c_stat_num_loops = 0; /* set statistic vars to zero */
+ c_stat_array_accesses = c_stat_sum_accesses = 0;
+ c_stat_full_opt = c_stat_sum_full = 0;
+ c_stat_no_opt = c_stat_sum_no = 0;
+ c_stat_lower_opt = c_stat_sum_lower = 0;
+ c_stat_upper_opt = c_stat_sum_upper = 0;
+ c_stat_or = c_stat_sum_or = 0;
+ c_stat_exception = c_stat_sum_exception = 0;
+#endif
+
+ /* init vars needed by all loops */
+ c_needs_redirection = false;
+ c_newstart = NULL;
+ c_old_xtablelength = exceptiontablelength;
+
+ /* loops have been topologically sorted */
+ lc = c_allLoops;
+ while (lc != NULL) {
+ optimize_single_loop(lc);
+
+#ifdef LOOP_DEBUG
+ printf(" *** Optimized loop *** \n");
+ fflush(stdout);
+#endif
+
+ lc = lc->next;
+ }
+#ifdef LOOP_DEBUG
+ printf("---*** All loops finished ***---\n");
+ fflush(stdout);
+#endif
+
+ /* if global BB list start is modified, set block to new start */
+ if (c_needs_redirection == true)
+ block = c_newstart;
+
+}
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+
+
+
--- /dev/null
+/* graph.c *********************************************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties.
+
+ Contains the functions which build a list, that represents the control
+ flow graph of the procedure, that is being analyzed.
+
+ Authors: Christopher Kruegel EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/17/02
+
+*******************************************************************************/
+
+void dF(int from, int blockIndex);
+
+void LoopContainerInit(struct LoopContainer *lc, int i)
+{
+ struct LoopElement *le = DMNEW(struct LoopElement, 1);
+
+ le->next = NULL;
+
+ lc->parent = NULL;
+
+ lc->tree_right = NULL;
+ lc->tree_down = NULL;
+
+ lc->exceptions = NULL;
+
+ lc->in_degree = 0;
+ le->node = lc->loop_head = i;
+ le->block = &block[i];
+
+ /* lc->nodes = (int *) malloc(sizeof(int)*block_count);
+ lc->nodes[0] = i; */
+
+ lc->nodes = le;
+}
+
+/* depthFirst() builds the control flow graph out of the intermediate code of
+ the procedure, that is to be optimized and stores the list in the global
+ variable c_dTable
+*/
+void depthFirst()
+{
+ int i, j;
+ struct depthElement *hp;
+
+/* allocate memory and init gobal variables needed by function dF(int, int) */
+
+ if ((c_defnum = (int *) malloc(block_count * sizeof(int))) == NULL)
+ c_mem_error();
+ if ((c_numPre = (int *) malloc(block_count * sizeof(int))) == NULL)
+ c_mem_error();
+ if ((c_parent = (int *) malloc(block_count * sizeof(int))) == NULL)
+ c_mem_error();
+ if ((c_reverse = (int *) malloc(block_count * sizeof(int))) == NULL)
+ c_mem_error();
+
+ if ((c_pre = (int **) malloc(block_count * sizeof(int *))) == NULL)
+ c_mem_error();
+
+ if ((c_dTable = (struct depthElement **) malloc(block_count * sizeof(struct depthElement *))) == NULL)
+ c_mem_error();
+
+ for (i = 0; i < block_count; ++i) {
+ c_defnum[i] = c_parent[i] = -1;
+ c_numPre[i] = c_reverse[i] = 0;
+
+ if ((c_pre[i] = (int *) malloc(block_count * sizeof(int))) == NULL)
+ c_mem_error();
+ c_dTable[i] = NULL;
+ }
+
+ c_globalCount = 0;
+ c_allLoops = NULL;
+
+ dF(-1, 0); /* call helper function dF that traverses basic block structure */
+}
+
+/* dF starts from the first block of the given procedure and traverses the
+ control flow graph in a depth-first order, thereby building up the adeacency
+ list c_dTable
+*/
+void dF(int from, int blockIndex)
+{
+ instruction *ip;
+ s4 *s4ptr;
+ int high, low, count;
+ struct depthElement *hp;
+ struct LoopContainer *tmp;
+ int cnt, *ptr;
+
+ if (from >= 0) {
+/* the current basic block has a predecessor (ie. is not the first one) */
+ if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL)
+ c_mem_error(); /* cretae new depth element */
+
+ hp->next = c_dTable[from]; /* insert values */
+ hp->value = blockIndex;
+ hp->changes = NULL;
+
+ c_dTable[from] = hp; /* insert into table */
+ }
+
+ if (from == blockIndex) { /* insert one node loops into loop container */
+ if ((tmp = (struct LoopContainer *) malloc(sizeof(struct LoopContainer))) == NULL)
+ c_mem_error();
+ LoopContainerInit(tmp, blockIndex);
+ tmp->next = c_allLoops;
+ c_allLoops = tmp;
+ }
+
+#ifdef C_DEBUG
+ if (blockIndex > block_count) {
+ fprintf(stderr, "DepthFirst: BlockIndex exceeded\n");
+ exit(1);
+ }
+#endif
+
+ ip = block[blockIndex].iinstr + block[blockIndex].icount -1;
+ /* set ip to last instruction */
+
+ if (c_defnum[blockIndex] == -1) { /* current block has not been visited */
+ c_defnum[blockIndex] = c_globalCount; /* update global count */
+ c_parent[blockIndex] = from; /* write parent block of current one */
+ c_reverse[c_globalCount] = blockIndex;
+ ++c_globalCount;
+
+ if (!block[blockIndex].icount) {
+ /* block does not contain instructions */
+ dF(blockIndex, blockIndex+1);
+ }
+ else { /* for all successors, do */
+ switch (ip->opc) { /* check type of last instruction */
+ case ICMD_RETURN:
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ case ICMD_ATHROW:
+ break; /* function returns -> end of graph */
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE: /* branch -> check next block */
+ dF(blockIndex, blockIndex + 1);
+ /* fall throu */
+
+ case ICMD_GOTO:
+ dF(blockIndex, block_index[ip->op1]);
+ break; /* visit branch (goto) target */
+
+ case ICMD_TABLESWITCH: /* switch statement */
+ s4ptr = ip->val.a;
+
+ dF(blockIndex, block_index[*s4ptr]); /* default branch */
+
+ s4ptr++;
+ low = *s4ptr;
+ s4ptr++;
+ high = *s4ptr;
+
+ count = (high-low+1);
+
+ while (--count >= 0) {
+ s4ptr++;
+ dF(blockIndex, block_index[*s4ptr]);
+ }
+ break;
+
+ case ICMD_LOOKUPSWITCH: /* switch statement */
+ s4ptr = ip->val.a;
+
+ dF(blockIndex, block_index[*s4ptr]); /* default branch */
+
+ ++s4ptr;
+ count = *s4ptr++;
+
+ while (--count >= 0) {
+ dF(blockIndex, block_index[s4ptr[1]]);
+ s4ptr += 2;
+ }
+ break;
+
+ case ICMD_JSR:
+ c_last_jump = blockIndex;
+ dF(blockIndex, block_index[ip->op1]);
+ break;
+
+ case ICMD_RET:
+ dF(blockIndex, c_last_jump+1);
+ break;
+
+ default:
+ dF(blockIndex, blockIndex + 1);
+ break;
+ }
+ }
+ }
+
+ for (ptr = c_pre[blockIndex], cnt = 0; cnt < c_numPre[blockIndex]; ++cnt, ++ptr)
+ {
+ if (*ptr == from)
+ break;
+ }
+
+ if (cnt >= c_numPre[blockIndex]) {
+ c_pre[blockIndex][c_numPre[blockIndex]] = from;
+ /* add predeccessors to list c_pre */
+ c_numPre[blockIndex]++; /* increase number of predecessors */
+ }
+
+}
+
+/* a slightly modified version of dF(int, int) that is used to traverse the part
+ of the control graph that is not reached by normal program flow but by the
+ raising of exceptions (code of catch blocks)
+*/
+void dF_Exception(int from, int blockIndex)
+{
+ instruction *ip;
+ s4 *s4ptr;
+ int high, low, count;
+ struct depthElement *hp;
+ struct LoopContainer *tmp;
+
+ if (c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
+ c_exceptionVisit[blockIndex] = 1;
+ else
+ return;
+
+ if (c_dTable[blockIndex] != NULL) /* back to regular code section */
+ return;
+
+ if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
+ if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL)
+ c_mem_error();
+
+ hp->next = c_exceptionGraph[from];
+ hp->value = blockIndex;
+ hp->changes = NULL;
+
+ c_exceptionGraph[from] = hp;
+ }
+
+#ifdef C_DEBUG
+ if (blockIndex > block_count) {
+ fprintf(stderr, "DepthFirst: BlockIndex exceeded\n");
+ exit(1);
+ }
+#endif
+
+ ip = block[blockIndex].iinstr + block[blockIndex].icount -1;
+
+ if (!block[blockIndex].icount)
+ dF_Exception(blockIndex, blockIndex+1);
+ else {
+ switch (ip->opc) {
+ case ICMD_RETURN:
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ case ICMD_ATHROW:
+ break;
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ dF_Exception(blockIndex, blockIndex + 1);
+ /* fall throu */
+
+ case ICMD_GOTO:
+ dF_Exception(blockIndex, block_index[ip->op1]);
+ break;
+
+ case ICMD_TABLESWITCH:
+ s4ptr = ip->val.a;
+
+ /* default branch */
+ dF_Exception(blockIndex, block_index[*s4ptr]);
+
+ s4ptr++;
+ low = *s4ptr;
+ s4ptr++;
+ high = *s4ptr;
+
+ count = (high-low+1);
+
+ while (--count >= 0) {
+ s4ptr++;
+ dF_Exception(blockIndex, block_index[*s4ptr]);
+ }
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ s4ptr = ip->val.a;
+
+ /* default branch */
+ dF_Exception(blockIndex, block_index[*s4ptr]);
+
+ ++s4ptr;
+ count = *s4ptr++;
+
+ while (--count >= 0) {
+ dF_Exception(blockIndex, block_index[s4ptr[1]]);
+ s4ptr += 2;
+ }
+ break;
+
+ case ICMD_JSR:
+ c_last_jump = blockIndex;
+ dF_Exception(blockIndex, block_index[ip->op1]);
+ break;
+
+ case ICMD_RET:
+ dF_Exception(blockIndex, c_last_jump+1);
+ break;
+
+ default:
+ dF_Exception(blockIndex, blockIndex + 1);
+ break;
+ }
+ }
+}
+
+/* Test function -> will be removed in final release
+*/
+void resultPass1()
+{
+ int i, j;
+ struct depthElement *hp;
+
+ printf("\n\n****** PASS 1 ******\n\n");
+ printf("Number of Nodes: %d\n\n", c_globalCount);
+
+ printf("Predecessors:\n");
+ for (i=0; i<block_count; ++i) {
+ printf("Block %d:\t", i);
+ for (j=0; j<c_numPre[i]; ++j)
+ printf("%d ", c_pre[i][j]);
+ printf("\n");
+ }
+ printf("\n");
+
+ printf("Graph:\n");
+ for (i=0; i<block_count; ++i) {
+ printf("Block %d:\t", i);
+ hp = c_dTable[i];
+
+ while (hp != NULL) {
+ printf("%d ", hp->value);
+ hp = hp->next;
+ }
+ printf("\n");
+ }
+ printf("\n");
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* loop.c **********************************************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties.
+
+ Contains the functions which use the control flow graph to do loop detection.
+ The loop detection is performed according to Lengauer-Tarjan algorithm
+ that uses dominator trees (found eg. in modern compiler implementation
+ by a.w. appel)
+
+ Authors: Christopher Kruegel EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/17/02
+
+*******************************************************************************/
+
+/* This function allocates and initializes variables, that are used by the
+ loop detection algorithm
+*/
+void setup()
+{
+ int i;
+
+ c_semi_dom = (int *) malloc(block_count * sizeof(int));
+ c_idom = (int *) malloc(block_count * sizeof(int));
+ c_same_dom = (int *) malloc(block_count * sizeof(int));
+ c_numBucket = (int *) malloc(block_count * sizeof(int));
+ c_ancestor = (int *) malloc(block_count * sizeof(int));
+ c_contains = (int *) malloc(block_count * sizeof(int));
+ c_stack = (int *) malloc(block_count * sizeof(int));
+
+ c_bucket = (int **) malloc(block_count * sizeof(int *));
+
+ for (i=0; i<block_count; ++i) {
+ c_numBucket[i] = 0;
+ c_stack[i] = c_ancestor[i] = c_semi_dom[i] = c_same_dom[i] = c_idom[i] = -1;
+
+ c_bucket[i] = (int *) malloc(block_count * sizeof(int));
+ }
+}
+
+/* This function is a helper function for dominators and has to find the
+ ancestor of the node v in the control graph, which semi-dominator has the
+ lowest def-num.
+*/
+int findLowAnc(int v)
+{
+ int u = v; /* u is the node which has the current lowest semi-dom */
+
+ while (c_ancestor[v] != -1) { /* as long as v has an ancestor, continue */
+ if (c_defnum[c_semi_dom[v]] < c_defnum[c_semi_dom[u]])
+ /* if v's semi-dom is smaller */
+ u = v; /* it gets the new current node u */
+ v = c_ancestor[v]; /* climb one step up in the tree */
+ }
+ return u; /* return node with the lowest semi-dominator def-num */
+}
+
+
+/* This function builds the dominator tree out of a given control flow graph and
+ stores its results in c_idom[]. It first calculates the number of possible
+ dominators in c_bucket and eventually determines the single dominator in a
+ final pass.
+*/
+void dominators()
+{
+ int i, j, semi, s, n, v, actual, p, y;
+
+ for (n=(c_globalCount-1); n>0; --n) { /* for all nodes (except last), do */
+ actual = c_reverse[n];
+ semi = p = c_parent[actual];
+
+ /* for all predecessors of current node, do */
+ for (i=0; i<c_numPre[actual]; ++i) {
+ v = c_pre[actual][i];
+
+ if (c_defnum[v] <= c_defnum[actual])
+ s = v; /* if predecessor has lower def-num than node */
+ /* it becomes candidate for semi dominator */
+ else
+ s = c_semi_dom[findLowAnc(v)];
+ /* else the semi-dominator of it's ancestor */
+ /* with lowest def-num becomes candidate */
+
+ if (c_defnum[s] < c_defnum[semi])
+ semi = s; /* if the def-num of the new candidate is lower */
+ /* than old one, it gets new semi dominator */
+ }
+
+ /* write semi dominator -> according to SEMIDOMINATOR THEOREM */
+ c_semi_dom[actual] = semi;
+ c_ancestor[actual] = p;
+
+ c_bucket[semi][c_numBucket[semi]] = actual;
+ c_numBucket[semi]++; /* defer calculation of dominator to final pass */
+
+
+ /* first clause of DOMINATOR THEOREM, try to find dominator now */
+ for (j=0; j<c_numBucket[p]; ++j) {
+ v = c_bucket[p][j];
+ y = findLowAnc(v);
+
+ if (c_semi_dom[y] == c_semi_dom[v])
+ c_idom[v] = p; /* if y's dominator is already known */
+ /* found it and write to c_idom */
+ else
+ c_same_dom[v] = y; /* wait till final pass */
+ }
+
+ c_numBucket[p] = 0;
+ }
+
+ /* final pass to get missing dominators ->second clause of DOMINATOR THEORM */
+ for (j=1; j<(c_globalCount-1); ++j) {
+ if (c_same_dom[c_reverse[j]] != -1)
+ c_idom[c_reverse[j]] = c_idom[c_same_dom[c_reverse[j]]];
+ }
+}
+
+/* A helper function needed by detectLoops() that checks, whether a given
+ connection between two nodes in the control flow graph is possibly part
+ of a loop (is a backEdge).
+*/
+int isBackEdge(int from, int to)
+{
+ int tmp = c_idom[to]; /* speed optimization: if the to-node is dominated */
+ while (tmp != -1) { /* by the from node as it is most of the time, */
+ if (tmp == from) /* there is no backEdge */
+ return 0;
+ tmp = c_idom[tmp];
+ }
+
+ tmp = c_idom[from]; /* if from-node doesn't dominate to-node, we have */
+ while (tmp != -1) { /* to climb all the way up from the from-node to */
+ if (tmp == to) /* the top to check, whether it is dominated by to */
+ return 1; /* if so, return a backedge */
+ tmp = c_idom[tmp];
+ }
+
+ return 0; /* else, there is no backedge */
+}
+
+
+/* These stack functions are helper functions for createLoop(int, int)
+ to manage the set of nodes in the current loop.
+*/
+void push(int i, struct LoopContainer *lc)
+{
+ struct LoopElement *le = lc->nodes, *t;
+
+ if (!c_contains[i])
+ {
+ t = DMNEW(struct LoopElement, 1);
+
+ t->node = i;
+ t->block = &block[i];
+
+ c_contains[i] = 1;
+
+ if (i < le->node)
+ {
+ t->next = lc->nodes;
+ lc->nodes = t;
+ }
+ else
+ {
+ while ((le->next != NULL) && (le->next->node < i))
+ le = le->next;
+
+ t->next = le->next;
+ le->next = t;
+ }
+
+ c_stack[c_stackPointer++] = i;
+ }
+}
+int pop()
+{
+ return (c_stack[--c_stackPointer]);
+}
+int isFull()
+{
+ return (c_stackPointer);
+}
+
+
+/* This function is a helper function, that finds all nodes, that belong to
+ the loop with a known header node and a member node of the loop (and a
+ back edge between these two nodes).
+*/
+void createLoop(int header, int member)
+{
+ int i, nextMember;
+
+ struct LoopContainer *currentLoop = (struct LoopContainer *) malloc(sizeof(struct LoopContainer));
+ LoopContainerInit(currentLoop, header); /* set up loop structure */
+
+ for (i=0; i<block_count; ++i)
+ c_contains[i] = 0;
+ c_contains[header] = 1;
+
+ c_stackPointer = 0; /* init stack with first node of the loop */
+ push(member, currentLoop);
+
+ while (isFull()) { /* while there are still unvisited nodes */
+ nextMember = pop();
+
+ /* push all predecessors, while they are not equal to loop header */
+ for (i=0; i<c_numPre[nextMember]; ++i)
+ push(c_pre[nextMember][i], currentLoop);
+ }
+
+ currentLoop->next = c_allLoops;
+ c_allLoops = currentLoop;
+}
+
+
+/* After all dominators have been calculated, the loops can be detected and
+ added to the global list c_allLoops.
+*/
+void detectLoops()
+{
+ int i;
+ struct depthElement *h;
+
+ /* for all edges in the control flow graph do */
+ for (i=0; i<block_count; ++i) {
+ h = c_dTable[i];
+
+ while (h != NULL) {
+ /* if it's a backedge, than add a new loop to list */
+ if (isBackEdge(i, h->value))
+ createLoop(h->value, i);
+ h = h->next;
+ }
+ }
+}
+
+/* This function is called by higher level routines to perform the loop
+ detection and set up the c_allLoops list.
+*/
+void analyseGraph()
+{
+ setup();
+ dominators();
+ detectLoops();
+}
+
+/* Test function -> will be removed in final release
+*/
+void resultPass2()
+{
+ int i, j;
+ struct LoopContainer *lc = c_allLoops;
+ struct LoopElement *le;
+
+ printf("\n\n****** PASS 2 ******\n\n");
+
+ printf("Loops:\n\n");
+
+ j=0;
+ while (lc != NULL) {
+ printf("Loop [%d]: ", ++j);
+
+ le = lc->nodes;
+ while (le != NULL) {
+ printf("%d ", le->node);
+ printf("\n");
+ le = le->next;
+ }
+
+ lc = lc->next;
+ }
+
+ printf("\n");
+
+}
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+
+
+
--- /dev/null
+/* loop.h **********************************************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties.
+
+ Main header file for array bound removal files
+
+ Authors: Christopher Kruegel EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/17/02
+
+*******************************************************************************/
+
+#ifndef __C_ARRAYBOUND_
+#define __C_ARRAYBOUND_
+
+/* #define LOOP_DEBUG */
+
+/* GLOBAL DEFINES */
+
+
+/* Different types for struct Trace */
+#define TRACE_UNKNOWN 0 /* unknown */
+#define TRACE_ICONST 1 /* integer constant value */
+#define TRACE_ALENGTH 2 /* array length value */
+#define TRACE_IVAR 3 /* integer variable reference */
+#define TRACE_AVAR 4 /* object (array) reference */
+
+/* The ways a variable can be used in a loop */
+#define ARRAY_INDEX 0 /* var used as array index */
+#define VAR_MOD 1 /* var changes its value */
+
+/* The way, integer variables change their values */
+#define D_UP 0 /* var is only increased */
+#define D_DOWN 1 /* var is only decreased */
+#define D_UNKNOWN 2 /* not known */
+
+/* The different types of operators in loop conditions */
+#define OP_EQ 0 /* operator: == */
+#define OP_LT 1 /* operator: < */
+#define OP_GE 2 /* operator: >= */
+#define OP_UNKNOWN 3 /* operator: unknown */
+
+/* Possible types of static tests (constraints) in struct Constraint */
+
+#define TEST_ZERO 0 /* check variable against const. lower bound */
+#define TEST_ALENGTH 1 /* check variable against array length */
+#define TEST_CONST_ZERO 2 /* check constant against const. lower bound */
+#define TEST_CONST_ALENGTH 3 /* check variable against array length */
+#define TEST_UNMOD_ZERO 4 /* check var. that is constant in loop against */
+ /* constant lower bound */
+#define TEST_UNMOD_ALENGTH 5 /* check var. that is constant in loop against */
+ /* array length */
+#define TEST_RS_ZERO 6 /* check constant part of loop condition against*/
+ /* constant lower bound */
+#define TEST_RS_ALENGTH 7 /* check constant part of loop condition against*/
+ /* array length */
+
+/* Possible types of bound check optimizations */
+#define OPT_UNCHECKED 0 /* access not checked yet - first visit */
+#define OPT_NONE 1 /* no optimization */
+#define OPT_FULL 2 /* fully remove bound check */
+#define OPT_LOWER 3 /* remove check againt zero */
+#define OPT_UPPER 4 /* remove check against array length */
+
+/* The different ways, remove_boundcheck(.) can be called */
+#define BOUNDCHECK_REGULAR 0 /* perform regular optimization */
+#define BOUNDCHECK_SPECIAL 1 /* only optimize header node - and ignore */
+ /* information from loop condition */
+
+#define LOOP_PART 0x1 /* a flag that marks a BB part of a loop */
+#define HANDLER_PART 0x2 /* a flag that marks a BB part of ex-handler */
+#define HANDLER_VISITED 0x4 /* flag to prevent loop if copying catch blocks */
+
+/* STRUCT DEFINITIONS */
+
+/* This struct records information about interesting vars (vars that are modified
+ or used as an array index in loops.
+*/
+struct LoopVar
+{
+ int value; /* reference to array of local variables */
+
+ int modified; /* set if value of var is changed */
+ int index; /* set if var is used as array index */
+
+ int static_l; /* var is never decremented -> static lower */
+ /* bound possible */
+ int static_u; /* var is never incremented -> static upper */
+ /* bound possible */
+ int dynamic_l;
+ int dynamic_l_v; /* variable is left side of loop condition in */
+ /* variable + dynamic_l >= right side */
+ int dynamic_u;
+ int dynamic_u_v; /* variable is left side of loop condition in */
+ /* variable + dynamic_u < right side */
+ struct LoopVar *next; /* list pointer */
+};
+
+/* This struct records the needed static test of variables before loop entry. */
+struct Constraint
+{
+ int type; /* type of test to perform */
+
+ int arrayRef; /* array reference involved in test (if any) */
+ int varRef; /* which variable to test (if involved) */
+ int constant; /* which constant to test (if involved) */
+
+ struct Constraint *next; /* list pointer */
+};
+
+/* This structure is used to record variables that change their value in loops. */
+struct Changes
+{
+ int var; /* variable involved */
+ int lower_bound; /* a minimum lower bound that is guaranteed */
+ int upper_bound; /* a maximum upper bound that is guaranteed */
+ /* IMPORTANT: if lower_bound > upper_bound */
+ /* there are no guarantees at all */
+};
+
+/* This struct is used to build the control flow graph and stores the variable
+ changes at the beginning of each basic block.
+*/
+struct depthElement
+{
+ int value; /* number of successor of this block */
+ struct depthElement *next; /* list pointer */
+ struct Changes **changes; /* pointer to array of variable changes */
+};
+
+/* Used to build a list of all basicblock, the loop consists of
+*/
+struct LoopElement
+{
+ int node;
+ basicblock *block;
+ struct LoopElement *next;
+};
+
+/* This structure stores informations about a single loop
+*/
+struct LoopContainer
+{
+ int toOpt; /* does this loop need optimization */
+
+ struct LoopElement *nodes; /* list of BBs this loop consists of */
+ int loop_head;
+ int in_degree; /* needed to topological sort loops to */
+ /* get the order of optimizing them */
+
+ struct LoopContainer *next; /* list pointer */
+ struct LoopContainer *parent; /* points to parent loop, if this BB */
+ /* is head of a loop */
+
+ struct LoopContainer *tree_right; /* used for tree hierarchie of loops */
+ struct LoopContainer *tree_down;
+
+ xtable *exceptions; /* list of exception in that loop */
+};
+
+/* This struct is needed to record the source of operands of intermediate code
+ instructions. The instructions are scanned backwards and the stack is
+ analyzed in order to determine the type of operand.
+*/
+struct Trace
+{
+ int type; /* the type of the operand */
+
+ int neg; /* set if negated */
+
+ int var; /* variable reference for IVAR */
+ /* array reference for AVAR/ARRAY */
+ int nr; /* instruction number in the basic block, where */
+ /* the trace is defined */
+ int constant; /* constant value for ICONST */
+ /* modifiers for IVAR */
+};
+
+
+
+/* FUNCTIONS */
+
+void c_mem_error()
+{
+ printf("C_ERROR: Not enough memeory\n");
+ exit(-1);
+}
+
+/* GLOBAL VARS */
+
+int c_debug_nr; /* a counter to number all BB with an unique */
+ /* value */
+
+/* modified by graph.c */
+
+int *c_defnum; /* array that stores a number for each node when*/
+ /* control flow graph is traveres depth first */
+int *c_parent; /* for each node that array stores its parent */
+int *c_reverse; /* for each def number that array stores the */
+ /* corresponding node */
+int c_globalCount; /* counter for def numbering */
+int *c_numPre; /* array that stores for each node its number */
+ /* predecessors */
+int **c_pre; /* array of array that stores predecessors */
+int c_last_jump; /* stores the source node of the last jsr instr */
+basicblock *c_last_target; /* stores the source BB of the last jsr instr */
+
+struct depthElement **c_dTable; /* adjacency list for control flow graph */
+struct depthElement **c_exceptionGraph; /* adjacency list for exception graph */
+
+struct LoopContainer *c_allLoops; /* list of all loops */
+struct LoopContainer *c_loop_root; /* root of loop hierarchie tree */
+
+int *c_exceptionVisit; /* array that stores a flag for each node part */
+ /* of the exception graph */
+
+/* modified by loop.c */
+
+int *c_semi_dom; /* store for each node its semi dominator */
+int *c_idom; /* store for each node its dominator */
+int *c_same_dom; /* temp array to hold nodes with same dominator */
+int *c_ancestor; /* store for each node its ancestor with lowest */
+ /* semi dominator */
+int *c_numBucket;
+int **c_bucket;
+
+int *c_contains; /* store for each node whether it's part of loop*/
+int *c_stack; /* a simple stack as array */
+int c_stackPointer; /* stackpointer */
+
+
+/* modified by analyze.c */
+
+struct LoopContainer *root; /* the root pointer for the hierarchie tree of */
+ /* all loops in that procedure */
+
+int c_needed_instr; /* number of instructions that have to be */
+ /* inserted before loop header to make sure */
+ /* array optimization is legal */
+int c_rs_needed_instr; /* number of instructions needed to load the */
+ /* value ofthe right side of the loop condition */
+int *c_nestedLoops; /* store for each node the header node of the */
+ /* loop this node belongs to, -1 for none */
+int *c_hierarchie; /* store a loop hierarchie */
+int *c_toVisit; /* set for each node that is part of the loop */
+
+int *c_current_loop; /* for each node:
+ /* store 0: node is not part of loop */
+ /* store 1: node is loop header */
+ /* store 2: node is in loop but not part of any */
+ /* nested loop
+ /* store 3: node is part of nested loop */
+
+int c_current_head; /* store number of node that is header of loop */
+int *c_var_modified; /* store for each local variable whether its */
+ /* value is changed in the loop */
+
+struct Trace *c_rightside; /* right side of loop condition */
+struct Constraint **c_constraints;
+ /* array that stores for each variable a list */
+ /* static tests (constraints) that have to be */
+ /* performed before loop entry */
+ /* IMPORTANT: c_constraints[maxlocals] stores */
+ /* the tests for constants and the */
+ /* right side of loop condition */
+
+struct LoopVar *c_loopvars; /* a list of all intersting variables of the */
+ /* current loop (variables that are modified or */
+ /* used as array index */
+
+basicblock *c_first_block_copied; /* pointer to the first block, that is copied */
+ /* during loop duplication */
+
+basicblock *c_last_block_copied; /* last block, that is copied during loop */
+ /* duplication */
+
+int *c_null_check; /* array to store for local vars, whether they */
+ /* need to be checked against the null reference*/
+ /* in the loop head */
+
+bool c_needs_redirection; /* if a loop header is inserted as first block */
+ /* into the global BB list, this is set to true */
+
+basicblock *c_newstart; /* if a loop header is inserted as first block */
+ /* into the gloal BB list, this pointer is the */
+ /* new start */
+int c_old_xtablelength; /* used to store the original tablelength */
+
+/* set debug mode */
+#define C_DEBUG
+
+
+/* declare statistic variables */
+#ifdef STATISTICS
+
+int c_stat_num_loops; /* number of loops */
+
+/* statistics per loop */
+int c_stat_array_accesses; /* number of array accesses */
+
+int c_stat_full_opt; /* number of fully optimized accesses */
+int c_stat_no_opt; /* number of not optimized accesses */
+int c_stat_lower_opt; /* number of accesses where check against zero */
+ /* is removed */
+int c_stat_upper_opt; /* number of accesses where check against array */
+ /* lengh is removed */
+int c_stat_or; /* set if optimization is cancelled because of */
+ /* or in loop condition */
+int c_stat_exception; /* set if optimization is cancelled because of */
+ /* index var modified in catch block */
+
+/* statistics per procedure */
+int c_stat_sum_accesses; /* number of array accesses */
+
+int c_stat_sum_full; /* number of fully optimized accesses */
+int c_stat_sum_no; /* number of not optimized accesses */
+int c_stat_sum_lower; /* number of accesses where check against zero */
+ /* is removed */
+int c_stat_sum_upper; /* number of accesses where check against array */
+ /* lengh is removed */
+int c_stat_sum_or; /* set if optimization is cancelled because of */
+ /* or in loop condition */
+int c_stat_sum_exception; /* set if optimization is cancelled because of */
+
+
+#endif
+
+#endif
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+
--- /dev/null
+/* tracing.c *******************************************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties.
+
+ Contains the functions which create a trace. A trace is a structure, that
+ contains the source of the arguments of a given instruction. For more
+ details see function tracing(basicblock, int, int) below.
+
+ Authors: Christopher Kruegel EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/17/02
+
+*******************************************************************************/
+
+/* Test function -> will be removed in final release
+*/
+void printTraceResult(struct Trace *p)
+{
+ printf("TRACE: ");
+
+ switch (p->type) {
+ case TRACE_UNKNOWN:
+ printf("\tUnknown");
+ break;
+ case TRACE_ICONST:
+ printf("\tconst - %d", p->constant);
+ break;
+ case TRACE_ALENGTH:
+ printf("\tarray - (%d)%d - %d", p->neg, p->var, p->constant);
+ break;
+ case TRACE_IVAR:
+ printf("\tivar - (%d)%d - %d", p->neg, p->var, p->constant);
+ break;
+ case TRACE_AVAR:
+ printf("\tavar - %d", p->var);
+ break;
+ }
+
+ printf("\n");
+}
+
+
+/* A function that creates a new trace structure and initializes its values
+*/
+struct Trace* create_trace(int type, int var, int constant, int nr)
+{
+ struct Trace *t;
+ if ((t = (struct Trace *) malloc(sizeof(struct Trace))) == NULL)
+ c_mem_error();
+
+ t->type = type;
+
+ t->neg = 1;
+ t->var = var;
+ t->nr = nr;
+
+ t->constant = constant;
+
+ return t;
+}
+
+/* When the function tracing(...) encounters an add instruction during its
+ backward scan over the instructions, it trys to identify the source of the
+ arguments of this add function. The following function performs this task.
+*/
+struct Trace* add(struct Trace* a, struct Trace* b)
+{
+ switch (a->type) { /* check the first argument of add. when it */
+ case TRACE_UNKNOWN: /* is unknown or array-address, return unknown */
+ case TRACE_AVAR:
+ return create_trace(TRACE_UNKNOWN, -1, 0, 0);
+
+ case TRACE_ICONST: /* when it is constant, check second argument */
+ switch (b->type) {
+ case TRACE_IVAR: /* when second argument is a variable value */
+ case TRACE_ALENGTH: /* or array length, just add the constant */
+ a->type = b->type;
+ a->var = b->var;
+ a->neg = b->neg;
+ a->constant += b->constant;
+ break;
+ case TRACE_UNKNOWN: /* when unknown/array ref. return unknown */
+ case TRACE_AVAR:
+ return create_trace(TRACE_UNKNOWN, -1, 0, 0);
+ case TRACE_ICONST: /* when both are constant, just add them */
+ a->constant += b->constant;
+ break;
+ }
+ break;
+
+ case TRACE_IVAR: /* when it is a variable value or array length, */
+ case TRACE_ALENGTH: /* check second argument */
+ switch (b->type) {
+ case TRACE_IVAR: /* when it is not a constant return unknown */
+ case TRACE_ALENGTH:
+ case TRACE_UNKNOWN:
+ case TRACE_AVAR:
+ return create_trace(TRACE_UNKNOWN, -1, 0, 0);
+ case TRACE_ICONST: /* when it is a constant, just add it */
+ a->constant += b->constant;
+ break;
+ }
+ break;
+ }
+
+ return a;
+}
+
+/* When the function tracing(...) encounters a neg instruction during its
+ backward scan over the instructions, it trys to identify the source of the
+ argument of this neg function. The following function performs this task.
+*/
+struct Trace* negate(struct Trace* a)
+{
+ switch (a->type) { /* check argument type */
+ case TRACE_IVAR: /* when it is variable/array length value */
+ case TRACE_ALENGTH:
+ a->neg = -(a->neg); /* invert negate flag */
+ a->constant = -(a->constant); /* and negate constant */
+ break;
+
+ case TRACE_ICONST: /* when it is a constant, negate it */
+ a->constant = -(a->constant);
+ break;
+
+ default:
+ a->type = TRACE_UNKNOWN; /* else return unknown */
+ break;
+ }
+
+ return a;
+}
+
+/* When the function tracing(...) encounters a sub instruction during its backward
+ scan over the instructions, it trys to identify the source of the arguments of
+ this sub function. The following function performs this task, by applaying the
+ negate function on the second argument and then adds the values.
+*/
+struct Trace* sub(struct Trace* a, struct Trace* b)
+{
+ struct Trace *c = negate(b);
+ return add(a, c);
+}
+
+
+/* When the function tracing(...) encounters an array length instruction during
+ its backward scan over the instructions, it trys to identify the source of
+ the argument ofthis array length function. The following function performs
+ this task.
+*/
+struct Trace* array_length(struct Trace* a)
+{
+ if (a->type == TRACE_AVAR) /* if argument is an array ref., mark the type */
+ a->type = TRACE_ALENGTH; /* as array length of this array reference */
+ else
+ a->type = TRACE_UNKNOWN; /* else it's unknown */
+
+ return a;
+}
+
+/* This function is used to identify the types of operands of an intermediate
+ code instruction.It is needed by functions, that analyze array accesses. If
+ something is stored into or loaded from an array, we have to find out, which
+ array really has been accessed. When a compare instruction is encountered at
+ a loop header, the type of its operands have to be detected to construct
+ dynamic bounds for some variables in the loop. This function returns a struct
+ Trace (see loop.h for more details about this structure). block is the basic
+ block to be examined, index holds the offset of the examined instruction in
+ this block. The arguments are retrieved by using the stack structure, the
+ compilation process sets up. During the backwards scan of the code, it is
+ possible, that other instructions temporaray put or get values from the stack
+ and hide the value, we are interested in below them. The value temp counts
+ the number of values on the stack, the are located beyond the target value.
+*/
+struct Trace* tracing(basicblock *block, int index, int temp)
+{
+ int args, retval;
+ instruction *ip;
+ methodinfo *m;
+
+ if (index >= 0) {
+ ip = block->iinstr+index;
+
+/* printf("TRACING with %d %d %d\n", index, temp, ip->opc);
+*/
+ switch (ip->opc) {
+
+ /* nop, nullcheckpop */
+ case ICMD_NOP: /* ... ==> ... */
+ return tracing(block, index-1, temp);
+ break;
+
+ case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
+ return tracing(block, index-1, temp+1);
+ break;
+
+ /* Constants */
+ case ICMD_LCONST:
+ case ICMD_DCONST:
+ case ICMD_FCONST:
+ case ICMD_ACONST:
+ if (temp > 0)
+ return tracing(block, index-1, temp-1);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_ICONST:
+ if (temp > 0) /* if the target argument is not on top */
+ return tracing(block, index-1, temp-1); /* look further */
+ else
+ return create_trace(TRACE_ICONST, -1, ip->val.i, index);
+ break; /* else, return the value, found at this instr. */
+
+ /* Load/Store */
+ case ICMD_LLOAD:
+ case ICMD_DLOAD:
+ case ICMD_FLOAD:
+ if (temp > 0)
+ return tracing(block, index-1, temp-1);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_ILOAD:
+ if (temp > 0)
+ return tracing(block, index-1, temp-1);
+ else
+ return create_trace(TRACE_IVAR, ip->op1, 0, index);
+ break;
+
+ case ICMD_ALOAD:
+ if (temp > 0)
+ return tracing(block, index-1, temp-1);
+ else
+ return create_trace(TRACE_AVAR, ip->op1, 0, index);
+ break;
+
+ case ICMD_LSTORE:
+ case ICMD_DSTORE:
+ case ICMD_FSTORE:
+ case ICMD_ISTORE:
+ case ICMD_ASTORE:
+ return tracing(block, index-1, temp+1);
+ break;
+
+
+ /* pop/dup/swap */
+ case ICMD_POP:
+ return tracing(block, index-1, temp+1);
+ break;
+
+ case ICMD_POP2:
+ return tracing(block, index-1, temp+2);
+ break;
+
+ case ICMD_DUP:
+ if (temp > 0)
+ return tracing(block, index-1, temp-1);
+ else
+ return tracing(block, index-1, temp);
+ break;
+
+ case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
+ switch (temp) {
+ case 0: /* when looking for top or third element, */
+ case 2: /* just return top element */
+ return tracing(block, index-1, 0);
+ case 1:
+ return tracing(block, index-1, 1);
+ default:
+ return tracing(block, index-1, temp-1);
+ }
+ break;
+
+ case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
+ switch (temp) {
+ case 0: /* when looking for top or third element */
+ case 2: /* just return top element */
+ return tracing(block, index-1, 0);
+ case 1: /* when looking for second or fourth element*/
+ case 3: /* just return second element */
+ return tracing(block, index-1, 1);
+ default:
+ return tracing(block, index-1, temp-2);
+ }
+ break;
+
+ case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
+ switch (temp) {
+ case 0:
+ case 3:
+ return tracing(block, index-1, 0);
+ case 1:
+ case 4:
+ return tracing(block, index-1, 1);
+ case 2:
+ return tracing(block, index-1, 2);
+ default:
+ return tracing(block, index-1, temp-2);
+ }
+ break;
+
+ case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
+ switch (temp) {
+ case 0:
+ case 3:
+ return tracing(block, index-1, 0);
+ case 1:
+ case 4:
+ return tracing(block, index-1, 1);
+ case 2:
+ return tracing(block, index-1, 2);
+ default:
+ return tracing(block, index-1, temp-2);
+ }
+ break;
+
+ case ICMD_DUP2_X2: /* .., a, b, c, d ==> ..., c, d, a, b, c, d */
+ switch (temp) {
+ case 0:
+ case 4:
+ return tracing(block, index-1, 0);
+ case 1:
+ case 5:
+ return tracing(block, index-1, 1);
+ case 2:
+ return tracing(block, index-1, 2);
+ case 3:
+ return tracing(block, index-1, 3);
+ default:
+ return tracing(block, index-1, temp-2);
+ }
+ break;
+
+ case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
+ switch (temp) {
+ case 0:
+ return tracing(block, index-1, 1);
+ case 1:
+ return tracing(block, index-1, 0);
+ default:
+ return tracing(block, index-1, temp);
+ }
+ break;
+
+ /* Interger operations */
+ case ICMD_INEG: /* ..., value ==> ..., - value */
+ if (temp > 0)
+ return tracing(block, index-1, temp);
+ else /* if an inter neg. operation is found, */
+ /* invokethe negate function */
+ return negate(tracing(block, index-1, temp));
+ break;
+
+ case ICMD_LNEG: /* ..., value ==> ..., - value */
+ case ICMD_I2L: /* ..., value ==> ..., value */
+ case ICMD_L2I: /* ..., value ==> ..., value */
+ case ICMD_INT2BYTE: /* ..., value ==> ..., value */
+ case ICMD_INT2CHAR: /* ..., value ==> ..., value */
+ case ICMD_INT2SHORT: /* ..., value ==> ..., value */
+ if (temp > 0)
+ return tracing(block, index-1, temp);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
+ if (temp > 0)
+ return tracing(block, index-1, temp+1);
+ else /* when add is encountered, invoke add func */
+ return add(tracing(block, index-1, 0), tracing(block, index-1, 1));
+ break;
+
+ case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
+ if (temp > 0)
+ return tracing(block, index-1, temp);
+ else /* when a constant is added, create a */
+ /* constant-trace and use add function */
+ return add(tracing(block, index-1, 0), create_trace(TRACE_ICONST, -1, ip->val.i, index));
+ break;
+
+ case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
+ if (temp > 0)
+ return tracing(block, index-1, temp+1);
+ else /* use sub function for sub instructions */
+ return sub(tracing(block, index-1, 1), tracing(block, index-1, 0));
+ break;
+
+ case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
+ if (temp > 0)
+ return tracing(block, index-1, temp);
+ else
+ return sub(tracing(block, index-1, 0), create_trace(TRACE_ICONST, -1, ip->val.i, index));
+ break;
+
+ case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
+ case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
+ case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
+ case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
+ case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
+ case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
+ case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
+ case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
+ case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
+ case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
+ case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
+ case ICMD_LAND:
+ case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
+ case ICMD_LOR:
+ case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
+ case ICMD_LXOR:
+ if (temp > 0)
+ return tracing(block, index-1, temp+1);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
+ case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
+ case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
+ case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
+ case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
+ case ICMD_LDIVPOW2: /* val.i = constant */
+ case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
+ case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
+ case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
+ case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
+ case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
+ case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
+ case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
+ case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
+ case ICMD_IREM0X10001: /* ..., value ==> ..., value % 0x100001 */
+ case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
+ case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
+ case ICMD_LREM0X10001: /* ..., value ==> ..., value % 0x10001 */
+ case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
+ case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
+ case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
+ case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
+ case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
+ if (temp > 0)
+ return tracing(block, index-1, temp);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_IINC: /* ..., value ==> ..., value + constant */
+ return tracing(block, index-1, temp);
+ break;
+
+
+ /* floating operations */
+ case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
+ case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
+ case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
+ case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
+ case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
+ case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
+ case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
+ case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
+ case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
+ case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
+ case ICMD_FCMPL: /* .., val1, val2 ==> ..., val1 fcmpl val2 */
+ case ICMD_DCMPL:
+ case ICMD_FCMPG: /* .., val1, val2 ==> ..., val1 fcmpg val2 */
+ case ICMD_DCMPG:
+ if (temp > 0)
+ return tracing(block, index-1, temp+1);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_FNEG: /* ..., value ==> ..., - value */
+ case ICMD_DNEG: /* ..., value ==> ..., - value */
+ case ICMD_I2F: /* ..., value ==> ..., (float) value */
+ case ICMD_L2F:
+ case ICMD_I2D: /* ..., value ==> ..., (double) value */
+ case ICMD_L2D:
+ case ICMD_F2I: /* ..., value ==> ..., (int) value */
+ case ICMD_D2I:
+ case ICMD_F2L: /* ..., value ==> ..., (long) value */
+ case ICMD_D2L:
+ case ICMD_F2D: /* ..., value ==> ..., (double) value */
+ case ICMD_D2F: /* ..., value ==> ..., (double) value */
+ if (temp > 0)
+ return tracing(block, index-1, temp);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ /* memory operations */
+ case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
+ if (temp > 0)
+ return tracing(block, index-1, temp);
+ else
+ return array_length(tracing(block, index-1, 0));
+ break;
+
+ case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
+ case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
+ case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
+ case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
+ case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
+ case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
+ case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
+ case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
+ if (temp > 0)
+ return tracing(block, index-1, temp+1);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
+ case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
+ case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
+ case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
+ case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
+ case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
+ case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
+ case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
+ return tracing(block, index-1, temp+3);
+ break;
+
+ case ICMD_PUTSTATIC: /* ..., value ==> ... */
+ case ICMD_PUTFIELD: /* ..., value ==> ... */
+ return tracing(block, index-1, temp+1);
+ break;
+
+ case ICMD_GETSTATIC: /* ... ==> ..., value */
+ case ICMD_GETFIELD: /* ... ==> ..., value */
+ if (temp > 0)
+ return tracing(block, index-1, temp-1);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+
+ /* branch: should not be encountered, but function calls possible */
+ case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
+ m = ip->val.a; /* get method pointer and */
+ args = ip->op1; /* number of arguments */
+ if (m->returntype != TYPE_VOID)
+ retval = 1; /* if function returns a value, it is on */
+ else /* top of stack */
+ retval = 0;
+
+ if (temp > 0) /* temp is increased by number of arguments */
+ /* less a possible result value */
+ return tracing(block, index-1, temp+(args-retval));
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_INVOKESPECIAL: /* ..., objectref, [arg1, [arg2 ...]] ==> . */
+ case ICMD_INVOKEVIRTUAL: /* ..., objectref, [arg1, [arg2 ...]] ==> . */
+ case ICMD_INVOKEINTERFACE: /* ..., objectref, [arg1, [arg2 ...]] ==> . */
+ m = ip->val.a;
+ args = ip->op1;
+ if (m->returntype != TYPE_VOID)
+ retval = 1;
+ else
+ retval = 0;
+
+ if (temp > 0) /* same as above but add 1 for object ref */
+ return tracing(block, index-1, temp+(args-retval+1));
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ /* special */
+ case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
+ case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
+ if (temp > 0)
+ return tracing(block, index-1, temp);
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_MULTIANEWARRAY: /* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
+ /* op1 = dimension */
+
+ if (temp > 0) /* temp increased by number of dimensions */
+ /* minus one for array ref */
+ return tracing(block, index-1, temp+(ip->op1 - 1));
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
+ if (ip->op1 != TYPE_VOID)
+ retval = 1;
+ else
+ retval = 0;
+
+ if (temp > 0) /* increase temp by 3 minus possible return */
+ /* value */
+ return tracing(block, index-1, temp+(3-retval));
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
+ if (ip->op1 != TYPE_VOID)
+ retval = 1;
+ else
+ retval = 0;
+ if (temp > 0)
+ return tracing(block, index-1, temp+(2-retval));
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
+ if (ip->op1 != TYPE_VOID)
+ retval = 1;
+ else
+ retval = 0;
+ if (temp > 0)
+ return tracing(block, index-1, temp+(1-retval));
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ break;
+
+ /* others */
+ default:
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+ } /* switch */
+ } /* if */
+ else
+ return create_trace(TRACE_UNKNOWN, -1, 0, index);
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
-all: all-redirect
+GZIP = --best
+all: Makefile
+
.SUFFIXES:
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps nat/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu nat/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
subdir = nat
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu nat/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile
-all-redirect: all-am
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-generic
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-generic
-mostlyclean: mostlyclean-am
+clean: clean-generic mostlyclean
-clean-am: clean-generic mostlyclean-am
+distclean: distclean-generic clean
+ -rm -f config.status
-clean: clean-am
-
-distclean-am: distclean-generic clean-am
-
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-generic distclean-am
+maintainer-clean: maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
-.PHONY: tags distdir info-am info dvi-am dvi check check-am \
-installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+.PHONY: tags distdir info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
Mark Probst EMAIL: cacao@complang.tuwien.ac.at
Philipp Tomsich EMAIL: cacao@complang.tuwien.ac.at
- Last Change: $Id: cacao.c 123 1999-01-28 19:48:49Z phil $
+ Last Change: $Id: cacao.c 132 1999-09-27 15:54:42Z chris $
*******************************************************************************/
#define OPT_GC1 22
#define OPT_GC2 23
#endif
+#define OPT_OLOOP 24
struct {char *name; bool arg; int value;} opts[] = {
{"classpath", true, OPT_CLASSPATH},
{"gc1", false, OPT_GC1},
{"gc2", false, OPT_GC2},
#endif
+ {"oloop", false, OPT_OLOOP},
{NULL, false, 0}
};
printf (" -log logfile ......... specify a name for the logfile\n");
printf (" -c(heck)b(ounds) ..... don't check array bounds\n");
printf (" s(ync) ....... don't check for synchronization\n");
+ printf (" -oloop ............... optimize array accesses in loops\n");
printf (" -l ................... don't start the class after loading\n");
printf (" -all ................. compile all methods, no execution\n");
#ifdef OLD_COMPILER
}
break;
+ case OPT_OLOOP:
+ opt_loops = true;
+ break;
+
default:
print_usage();
exit(10);
Changes: Mark Probst (schani) EMAIL: cacao@complang.tuwien.ac.at
Philipp Tomsich (phil) EMAIL: cacao@complang.tuwien.ac.at
- Last Change: $Id: global.h 118 1999-01-20 14:58:16Z andi $
+ Last Change: $Id: global.h 132 1999-09-27 15:54:42Z chris $
*******************************************************************************/
} fieldinfo;
+struct basicblock;
/* exceptiontable *************************************************************/
+typedef struct xtable { /* exceptiontable entry in a method */
+ s4 startpc; /* start pc of guarded area (inclusive) */
+ struct basicblock *start;
+
+ s4 endpc; /* end pc of guarded area (exklusive) */
+ struct basicblock *end;
+
+ s4 handlerpc; /* pc of exception handler */
+ struct basicblock *handler;
+
+ classinfo *catchtype; /* catchtype of exception (NULL == catchall) */
+ struct xtable *next; /* used to build a list of exception when */
+ /* loops are copied */
+ struct xtable *down; /* instead of the old array, a list is used */
+} xtable;
+
+
typedef struct exceptiontable { /* exceptiontable entry in a method */
s4 startpc; /* start pc of guarded area (inclusive) */
s4 endpc; /* end pc of guarded area (exklusive) */
u1 *jcode; /* pointer to JavaVM code */
s4 exceptiontablelength;/* exceptiontable length */
- exceptiontable *exceptiontable; /* the exceptiontable */
+ exceptiontable *exceptiontable;
+ /* the exceptiontable */
u1 *stubroutine; /* stub for compiling or calling natives */
s4 mcodelength; /* legth of generated machine code */
Author: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
- Last Change: $Id: parse.c 115 1999-01-20 01:52:45Z phil $
+ Last Change: $Id: parse.c 132 1999-09-27 15:54:42Z chris $
*******************************************************************************/
/* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
/* additional MONITOREXITS are reached by branches which are 3 bytes */
- iptr = instr = DMNEW(instruction, jcodelength + 5);
+ iptr = instr = DMNEW(instruction, jcodelength + 5);
/* initialize block_index table (unrolled four times) */
/* compute branch targets of exception table */
+ extable = DMNEW(xtable, exceptiontablelength + 1);
+
for (i = 0; i < exceptiontablelength; i++) {
- p = extable[i].startpc;
+
+ p = extable[i].startpc = raw_extable[i].startpc;
bound_check(p);
block_insert(p);
- p = extable[i].endpc;
+
+ p = extable[i].endpc = raw_extable[i].endpc;
bound_check1(p);
if (p < jcodelength)
block_insert(p);
- p = extable[i].handlerpc;
+
+ p = extable[i].handlerpc = raw_extable[i].handlerpc;
bound_check(p);
block_insert(p);
+
+ extable[i].catchtype = raw_extable[i].catchtype;
+
+ extable[i].next = NULL;
+ extable[i].down = &extable[i+1];
}
+ if (exceptiontablelength > 0)
+ extable[exceptiontablelength-1].down = NULL;
+ else
+ extable = NULL;
+
s_count = 1 + exceptiontablelength; /* initialize stack element counter */
#ifdef USE_THREADS
bptr = block = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
b_count = 0;
+ c_debug_nr = 0;
/* additional block if target 0 is not first intermediate instruction */
bptr->type = BBTYPE_STD;
bptr->branchrefs = NULL;
bptr->pre_count = 0;
+ bptr->debug_nr = c_debug_nr++;
bptr++;
b_count++;
+ (bptr - 1)->next = bptr;
+
}
/* allocate blocks */
+
for (p = 0; p < jcodelength; p++)
+
if (block_index[p] & 1) {
bptr->iinstr = instr + (block_index[p] >> 1);
+ bptr->debug_nr = c_debug_nr++;
if (b_count != 0)
(bptr - 1)->icount = bptr->iinstr - (bptr - 1)->iinstr;
bptr->mpc = -1;
bptr->flags = -1;
+ bptr->lflags = 0;
bptr->type = BBTYPE_STD;
bptr->branchrefs = NULL;
block_index[p] = b_count;
bptr->pre_count = 0;
bptr++;
b_count++;
+
+ (bptr - 1)->next = bptr;
}
/* allocate additional block at end */
+
+ bptr->instack = bptr->outstack = NULL;
+ bptr->indepth = bptr->outdepth = 0;
bptr->iinstr = NULL;
(bptr - 1)->icount = (instr + instr_count) - (bptr - 1)->iinstr;
bptr->icount = 0;
bptr->mpc = -1;
bptr->flags = -1;
+ bptr->lflags = 0;
bptr->type = BBTYPE_STD;
bptr->branchrefs = NULL;
bptr->pre_count = 0;
+ bptr->debug_nr = c_debug_nr++;
+
+ (bptr - 1)->next = bptr;
+ bptr->next = NULL;
+
+ last_block = bptr;
+
+
+
+ for (i = 0; i < exceptiontablelength; ++i) {
+ p = extable[i].startpc;
+ extable[i].start = block + block_index[p];
+
+ p = extable[i].endpc;
+ extable[i].end = block + block_index[p];
+
+ p = extable[i].handlerpc;
+ extable[i].handler = block + block_index[p];
+ }
}
}
#else
#define COUNT(cnt)
#endif
-
+
#define STACKRESET {curstack=0;stackdepth=0;}
#define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");}
int superblockend, repeat, deadcode;
instruction *iptr = instr;
basicblock *bptr, *tbptr;
- s4 *s4ptr;
+ s4 *s4ptr;
+ void* *tptr;
+ xtable *ex;
arguments_num = 0;
new = stack;
b_index = bptr - block;
while (--len >= 0) {
opcode = iptr->opc;
+ iptr->target = NULL;
switch (opcode) {
/* pop 0 push 0 */
/* iptr[1].opc = ICMD_NOP; */
OP1_0(TYPE_INT);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
COUNT(count_pcmd_bra);
break;
iptr[2].opc = ICMD_NOP; */
OP1_0(TYPE_LNG);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
COUNT(count_pcmd_bra);
COUNT(count_pcmd_op);
COUNT(count_pcmd_bra);
OP1_0(TYPE_ADR);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
break;
#endif
OP1_0(TYPE_INT);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
break;
case ICMD_GOTO:
COUNT(count_pcmd_bra);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
SETDST;
superblockend = true;
MARKREACHED(tbptr, copy);
i = *s4ptr++; /* low */
i = *s4ptr++ - i + 1; /* high */
+
+ tptr = DMNEW(void*, i+1);
+ iptr->target = (void *) tptr;
+
+ tptr[0] = (void *) tbptr;
+ tptr++;
+
while (--i >= 0) {
tbptr = block + block_index[*s4ptr++];
+
+ tptr[0] = (void *) tbptr;
+ tptr++;
+
MARKREACHED(tbptr, copy);
}
SETDST;
tbptr = block + block_index[*s4ptr++]; /* default */
MARKREACHED(tbptr, copy);
i = *s4ptr++; /* count */
+
+ tptr = DMNEW(void*, i+1);
+ iptr->target = (void *) tptr;
+
+ tptr[0] = (void *) tbptr;
+ tptr++;
+
while (--i >= 0) {
tbptr = block + block_index[s4ptr[1]];
+
+ tptr[0] = (void *) tbptr;
+ tptr++;
+
MARKREACHED(tbptr, copy);
s4ptr += 2;
}
COUNT(count_pcmd_bra);
OP2_0(TYPE_INT);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
break;
COUNT(count_pcmd_bra);
OP2_0(TYPE_ADR);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
break;
/* iptr[1].opc = ICMD_NOP; */
OP2_0(TYPE_LNG);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
MARKREACHED(tbptr, copy);
COUNT(count_pcmd_bra);
break;
case ICMD_JSR:
OP0_1(TYPE_ADR);
tbptr = block + block_index[iptr->op1];
+
+ iptr[0].target = (void *) tbptr;
+
tbptr->type=BBTYPE_SBR;
MARKREACHED(tbptr, copy);
OP1_0ANY;
else
count_block_stack[bptr->indepth]++;
len = bptr->icount;
- if (len <= 10)
- count_block_size_distribution[len - 1]++;
+ if (len < 10)
+ count_block_size_distribution[len]++;
else if (len <= 12)
count_block_size_distribution[10]++;
else if (len <= 14)
static void show_icmd_method()
{
- int b, i, j, last;
+ int i, j, last;
int deadcode;
s4 *s4ptr;
instruction *iptr;
-
+ basicblock *bptr;
+ void **tptr;
+ xtable *ex;
+
printf("\n");
unicode_fprint(stdout, class->name);
printf(".");
printf ("\n\nMax locals: %d\n", (int) maxlocals);
printf ("Max stack: %d\n", (int) maxstack);
- printf ("Exceptions:\n");
- for (i = 0; i < exceptiontablelength; i++) {
- printf(" L%03d ... ", block_index[extable[i].startpc]);
- printf("L%03d = ", block_index[extable[i].endpc]);
- printf("L%03d\n", block_index[extable[i].handlerpc]);
+ printf ("Exceptions (Number: %d):\n", exceptiontablelength);
+ for (ex = extable; ex != NULL; ex = ex->down) {
+ printf(" L%03d ... ", ex->start->debug_nr );
+ printf("L%03d = ", ex->end->debug_nr);
+ printf("L%03d\n", ex->handler->debug_nr);
}
printf ("Local Table:\n");
printf("\n");
}
- for (b = 0; b < block_count; b++)
- if (block[b].flags != BBDELETED) {
- deadcode = block[b].flags <= BBREACHED;
+
+ for (bptr = block; bptr != NULL; bptr = bptr->next)
+ if (bptr->flags != BBDELETED) {
+ deadcode = bptr->flags <= BBREACHED;
printf("[");
if (deadcode)
for (j = maxstack; j > 0; j--)
printf(" ? ");
else
- print_stack(block[b].instack);
- printf("] L%03d(%d):\n", b, block[b].pre_count);
- iptr = block[b].iinstr;
- i = iptr - instr;
- for (last = i + block[b].icount; i < last; i++, iptr++) {
+ print_stack(bptr->instack);
+ printf("] L%03d(%d - %d):\n", bptr->debug_nr, bptr->icount, bptr->pre_count);
+ iptr = bptr->iinstr;
+
+ for (i=0; i < bptr->icount; i++, iptr++) {
printf("[");
if (deadcode) {
for (j = maxstack; j > 0; j--)
case ICMD_IINC:
printf(" %d + %d", iptr->op1, iptr->val.i);
break;
+
+ case ICMD_IASTORE:
+ case ICMD_SASTORE:
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_LASTORE:
+ case ICMD_DASTORE:
+ case ICMD_FASTORE:
+ case ICMD_AASTORE:
+
+ case ICMD_IALOAD:
+ case ICMD_SALOAD:
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_LALOAD:
+ case ICMD_DALOAD:
+ case ICMD_FALOAD:
+ case ICMD_AALOAD:
+ if (iptr->op1 != 0)
+ printf("(opt.)");
+ break;
+
case ICMD_RET:
case ICMD_ILOAD:
case ICMD_LLOAD:
case ICMD_IF_LGE:
case ICMD_IF_LGT:
case ICMD_IF_LLE:
- printf("(%d) L%03d", iptr->val.i, block_index[iptr->op1]);
+ printf("(%d) L%03d", iptr->val.i, ((basicblock *) iptr->target)->debug_nr);
break;
case ICMD_JSR:
case ICMD_GOTO:
case ICMD_IF_LCMPLE:
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
- printf(" L%03d", block_index[iptr->op1]);
+ printf(" L%03d", ((basicblock *) iptr->target)->debug_nr);
break;
case ICMD_TABLESWITCH:
+
s4ptr = iptr->val.a;
- printf(" L%03d;", block_index[*s4ptr++]); /* default */
+ tptr = (void **) iptr->target;
+
+ printf(" L%03d;", ((basicblock *) *tptr)->debug_nr);
+ /* default */
+
+ s4ptr++;
+ tptr++;
+
j = *s4ptr++; /* low */
j = *s4ptr++ - j; /* high */
while (j >= 0) {
- printf(" L%03d", block_index[*s4ptr++]);
+ printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
+ tptr++;
j--;
}
break;
case ICMD_LOOKUPSWITCH:
s4ptr = iptr->val.a;
- printf(" L%d", block_index[*s4ptr++]); /* default */
- j = *s4ptr++; /* count */
+ tptr = (void **) iptr->target;
+
+ printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
+ s4ptr++; /* default */
+ j = *s4ptr; /* count */
+ tptr++;
+
while (--j >= 0) {
- printf(" L%03d", block_index[s4ptr[1]]);
- s4ptr += 2;
+ printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
+ tptr++;
}
break;
}
if (showdisassemble && (!deadcode)) {
printf("\n");
- i = block[b].mpc;
+ i = bptr->mpc;
s4ptr = (s4 *) (method->mcode + dseglen + i);
- for (; i < block[b + 1].mpc; i += 4, s4ptr++) {
- disassinstr(*s4ptr, i);
- }
- printf("\n");
- }
+
+ if (bptr->next != NULL) {
+ for (; i < bptr->next->mpc; i += 4, s4ptr++) {
+ disassinstr(*s4ptr, i);
+ }
+ printf("\n");
+ }
+ else {
+ for (; s4ptr < (s4 *) (method->mcode + method->mcodelength); i += 4, s4ptr++) {
+ disassinstr(*s4ptr, i);
+ }
+ printf("\n");
+ }
+ }
}
- i = block[b].mpc;
+
+ /*
+ i = bptr->mpc;
s4ptr = (s4 *) (method->mcode + dseglen + i);
if (showdisassemble && (s4ptr < (s4 *) (method->mcode + method->mcodelength))) {
printf("\n");
}
printf("\n");
}
+ */
}
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
-all: all-redirect
+GZIP = --best
+all: Makefile
+
.SUFFIXES:
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps tst/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu tst/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
subdir = tst
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu tst/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile
-all-redirect: all-am
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-generic
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-generic
-mostlyclean: mostlyclean-am
+clean: clean-generic mostlyclean
-clean-am: clean-generic mostlyclean-am
+distclean: distclean-generic clean
+ -rm -f config.status
-clean: clean-am
-
-distclean-am: distclean-generic clean-am
-
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-generic distclean-am
+maintainer-clean: maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
-.PHONY: tags distdir info-am info dvi-am dvi check check-am \
-installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+.PHONY: tags distdir info dvi installcheck install-exec install-data \
+install uninstall all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
check:
// ************************ test array bounds ******************************
public static void testarraybounds(byte[] ba, int i) {
-
p ("testarraybounds: " + (i - 10));
ba[i-10] = 0;
p ("testarraybounds: " + (i - 5));
p ("testarraybounds: " + (i + 5));
ba[i+5] = 0;
p ("testarraybounds: " + (i + 10));
- ba[i+10] = 0;
+ ba[i+10] = 0;
}
p ("error: exception not thrown");
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+(-1));
+ p ("exception_1: out of bounds: "+(-1));
}
try {
p ("array bound check: byte array load");
p ("error: exception not thrown");
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+(-1));
+ p ("exception_2: out of bounds: "+(-1));
}
try {
testarraybounds(ba, 5);
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+5);
+ p ("exception_3: out of bounds: "+5);
}
try {
testarraybounds(ba, 50);
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+50);
+ p ("exception_4: out of bounds: "+50);
}
try {
testarraybounds(ba, 100);
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+100);
+ p ("exception_5: out of bounds: "+100);
}
try {
ba[-4] = 0;
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+(-4));
+ p ("exception_6: out of bounds: "+(-4));
}
try {
ba[-3] = 0;
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+(-3));
+ p ("exception_7: out of bounds: "+(-3));
}
+ System.out.println("starting 8. loop");
+
for (i=-2; i<102; i++) {
try {
ba[i] = (byte) (i-50);
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+i);
+ p ("exception_8: out of bounds: "+i);
}
}
+
try {
ba[102] = 0;
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+102);
+ p ("exception_9: out of bounds: "+102);
}
try {
ba[103] = 0;
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+103);
+ p ("exception_10: out of bounds: "+103);
}
for (i=0; i<100; i++) p (ba[i]);
+
+
p ("-------- test short arrays");
short[] sa = null;
p ("error: exception not thrown");
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+(-1));
+ p ("exception_11: out of bounds: "+(-1));
}
try {
p ("array bound check: short array load");
p ("error: exception not thrown");
}
catch (ArrayIndexOutOfBoundsException c) {
- p ("exception: out of bounds: "+(-1));
+ p ("exception_12: out of bounds: "+(-1));
}
for (i=0; i<100; i++) sa[i] = (short) (i-50);
for (i=0; i<100; i++) p (sa[i]);
+
p ("-------- test int arrays");
}
}
}
+
-
-
}
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
noinst_LIBRARIES = @LIBTHREAD@
EXTRA_LIBRARIES = libthreads.a
-libthreads_a_SOURCES = locks.c locks.h thread.c thread.h threadio.c threadio.h
+libthreads_a_SOURCES = locks.c locks.h \
+ thread.c thread.h \
+ threadio.c threadio.h
-
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/@SYSDEP_DIR@
+INCLUDES=-I$(top_srcdir) -I$(top_srcdir)/@SYSDEP_DIR@
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
libthreads_a_OBJECTS = locks.o thread.o threadio.o
AR = ar
CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
+GZIP = --best
+DEP_FILES = .deps/locks.P .deps/thread.P .deps/threadio.P
SOURCES = $(libthreads_a_SOURCES)
OBJECTS = $(libthreads_a_OBJECTS)
-all: all-redirect
+all: Makefile $(LIBRARIES)
+
.SUFFIXES:
.SUFFIXES: .S .c .o .s
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps threads/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu threads/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
maintainer-clean-noinstLIBRARIES:
-.c.o:
- $(COMPILE) -c $<
-
.s.o:
$(COMPILE) -c $<
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
- && mkid -f$$here/ID $$unique $(LISP)
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
subdir = threads
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu threads/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile $(LIBRARIES)
-all-redirect: all-am
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+ -rm -rf .deps
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+ @-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+ < .deps/$(*F).p > .deps/$(*F).P
+ @-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
- mostlyclean-tags mostlyclean-generic
-
-mostlyclean: mostlyclean-am
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
-clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
- mostlyclean-am
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \
+ clean-generic mostlyclean
-clean: clean-am
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-depend distclean-generic clean
+ -rm -f config.status
-distclean-am: distclean-noinstLIBRARIES distclean-compile \
- distclean-tags distclean-generic clean-am
-
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-generic distclean-am
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
-check-am installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info dvi \
+installcheck install-exec install-data install uninstall all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# PARTICULAR PURPOSE.
-SHELL = @SHELL@
+SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
+DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
noinst_LIBRARIES = libtoolbox.a
-libtoolbox_a_SOURCES = memory.c memory.h loging.c loging.h chain.c chain.h tree.c tree.h list.c list.h
+libtoolbox_a_SOURCES = memory.c memory.h \
+ loging.c loging.h \
+ chain.c chain.h \
+ tree.c tree.h \
+ list.c list.h
-
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/@SYSDEP_DIR@
+INCLUDES=-I$(top_srcdir) -I$(top_srcdir)/@SYSDEP_DIR@
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
libtoolbox_a_OBJECTS = memory.o loging.o chain.o tree.o list.o
AR = ar
CFLAGS = @CFLAGS@
-COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
-GZIP_ENV = --best
+GZIP = --best
+DEP_FILES = .deps/chain.P .deps/list.P .deps/loging.P .deps/memory.P \
+.deps/tree.P
SOURCES = $(libtoolbox_a_SOURCES)
OBJECTS = $(libtoolbox_a_OBJECTS)
-all: all-redirect
+all: Makefile $(LIBRARIES)
+
.SUFFIXES:
.SUFFIXES: .S .c .o .s
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps toolbox/Makefile
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu toolbox/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
maintainer-clean-noinstLIBRARIES:
-.c.o:
- $(COMPILE) -c $<
-
.s.o:
$(COMPILE) -c $<
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS)'; \
- unique=`for i in $$list; do echo $$i; done | \
- awk ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
- && mkid -f$$here/ID $$unique $(LISP)
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
subdir = toolbox
distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu toolbox/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
done
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
-check-am: all-am
-check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am:
-install-exec: install-exec-am
-
-install-data-am:
-install-data: install-data-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am:
-uninstall: uninstall-am
-all-am: Makefile $(LIBRARIES)
-all-redirect: all-am
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+ -rm -rf .deps
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+ @-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+ < .deps/$(*F).p > .deps/$(*F).P
+ @-rm -f .deps/$(*F).p
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
- mostlyclean-tags mostlyclean-generic
-
-mostlyclean: mostlyclean-am
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
-clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
- mostlyclean-am
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \
+ clean-generic mostlyclean
-clean: clean-am
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-depend distclean-generic clean
+ -rm -f config.status
-distclean-am: distclean-noinstLIBRARIES distclean-compile \
- distclean-tags distclean-generic clean-am
-
-distclean: distclean-am
-
-maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-generic distclean-am
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-maintainer-clean: maintainer-clean-am
-
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
-check-am installcheck-am installcheck install-exec-am install-exec \
-install-data-am install-data install-am install uninstall-am uninstall \
-all-redirect all-am all installdirs mostlyclean-generic \
-distclean-generic clean-generic maintainer-clean-generic clean \
-mostlyclean distclean maintainer-clean
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info dvi \
+installcheck install-exec install-data install uninstall all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.