From 4ac5116f91e794bb6d7a85eebcfe75b72af27d19 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 27 Sep 1999 15:54:42 +0000 Subject: [PATCH] narray first check in --- Makefile | 559 +++++++ Makefile.in | 340 +++-- aclocal.m4 | 21 +- alpha/Makefile.in | 114 +- alpha/ngen.c | 108 +- comp/Makefile.in | 113 +- config.h.in | 11 +- configure | 344 ++--- doc/array.tex | 375 +++++ global.h | 23 +- jit.c | 89 +- jit.h | 1 + jit/Makefile.in | 109 +- jit/jitdef.h | 12 + jit/mcode.c | 6 +- jit/parse.c | 58 +- jit/reg.c | 13 +- jit/stack.c | 172 ++- main.c | 9 +- mips/Makefile.in | 113 +- mm/Makefile.in | 168 +- narray/analyze.c | 3564 +++++++++++++++++++++++++++++++++++++++++++ narray/graph.c | 401 +++++ narray/loop.c | 293 ++++ narray/loop.h | 343 +++++ narray/tracing.c | 647 ++++++++ nat/Makefile.in | 109 +- src/cacao/cacao.c | 9 +- src/vm/global.h | 23 +- src/vm/jit/parse.c | 58 +- src/vm/jit/stack.c | 172 ++- tests/Makefile.in | 109 +- tests/jctest.java | 36 +- threads/Makefile.in | 165 +- toolbox/Makefile.in | 168 +- 35 files changed, 7763 insertions(+), 1092 deletions(-) create mode 100644 Makefile create mode 100644 doc/array.tex create mode 100644 narray/analyze.c create mode 100644 narray/graph.c create mode 100644 narray/loop.c create mode 100644 narray/loop.h create mode 100644 narray/tracing.c diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..b4bcb5b70 --- /dev/null +++ b/Makefile @@ -0,0 +1,559 @@ +# 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: diff --git a/Makefile.in b/Makefile.in index 81eaabe24..38aaff47a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -10,10 +10,10 @@ # 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@ @@ -34,7 +34,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -48,7 +48,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -74,15 +74,22 @@ THREAD_OBJ = @THREAD_OBJ@ 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) @@ -93,10 +100,42 @@ 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@ - +>>>>>>> 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@ @@ -117,58 +156,53 @@ cacao_LDFLAGS = 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: @@ -193,15 +227,15 @@ install-binPROGRAMS: $(bin_PROGRAMS) $(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: @@ -213,9 +247,6 @@ distclean-noinstPROGRAMS: maintainer-clean-noinstPROGRAMS: -.c.o: - $(COMPILE) -c $< - .s.o: $(COMPILE) -c $< @@ -253,65 +284,41 @@ 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; \ - 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 | \ @@ -337,125 +344,152 @@ top_distdir = $(distdir) # 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 \ @@ -470,12 +504,13 @@ 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 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 @@ -513,11 +548,27 @@ nativetypes.hh @SYSDEP_DIR@/offsets.h nativetable.hh: cacaoh @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 \ @@ -525,6 +576,7 @@ jit.o: jit.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: diff --git a/aclocal.m4 b/aclocal.m4 index f23ba2904..0520b196d 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,7 +1,7 @@ -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. @@ -20,7 +20,7 @@ dnl Usage: 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] @@ -30,8 +30,8 @@ if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then 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. @@ -43,6 +43,15 @@ AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) 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. # diff --git a/alpha/Makefile.in b/alpha/Makefile.in index 9862c4222..d9d7b72dc 100644 --- a/alpha/Makefile.in +++ b/alpha/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -71,8 +71,9 @@ SYSDEP_DIR = @SYSDEP_DIR@ 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 = @@ -82,13 +83,14 @@ DIST_COMMON = Makefile.am Makefile.in 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 @@ -101,75 +103,67 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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. diff --git a/alpha/ngen.c b/alpha/ngen.c index bd6d78252..69771a081 100644 --- a/alpha/ngen.c +++ b/alpha/ngen.c @@ -11,7 +11,7 @@ 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 $ *******************************************************************************/ @@ -45,7 +45,9 @@ in the documention file: calling.doc /* 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++ @@ -326,6 +328,7 @@ static void gen_mcode() varinfo *var; basicblock *bptr; instruction *iptr; + xtable *ex; { int p, pa, t, l, r; @@ -373,14 +376,45 @@ static void gen_mcode() (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; @@ -542,8 +576,8 @@ static void gen_mcode() /* 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) { @@ -600,7 +634,7 @@ static void gen_mcode() } /* walk through all instructions */ - + src = bptr->instack; len = bptr->icount; for (iptr = bptr->iinstr; @@ -1848,13 +1882,22 @@ static void gen_mcode() /* 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 */ @@ -1902,6 +1945,7 @@ static void gen_mcode() 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); @@ -2044,6 +2088,7 @@ static void gen_mcode() 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])); @@ -2972,6 +3017,9 @@ nowperformreturn: case ICMD_TABLESWITCH: /* ..., index ==> ... */ { s4 i, l, *s4ptr; + void **tptr; + + tptr = (void **) iptr->target; s4ptr = iptr->val.a; l = s4ptr[1]; /* low */ @@ -2998,13 +3046,20 @@ nowperformreturn: 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; } } @@ -3020,6 +3075,9 @@ nowperformreturn: case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */ { s4 i, l, val, *s4ptr; + void **tptr; + + tptr = (void **) iptr->target; s4ptr = iptr->val.a; l = s4ptr[0]; /* default */ @@ -3029,6 +3087,8 @@ nowperformreturn: 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); @@ -3044,11 +3104,16 @@ nowperformreturn: 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; } @@ -3377,7 +3442,7 @@ makeactualcall: 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); @@ -3386,9 +3451,13 @@ makeactualcall: default: sprintf (logtext, "Unknown pseudo command: %d", iptr->opc); error(); + + + } /* switch */ + } /* for instruction */ - + /* copy values to interface registers */ src = bptr->outstack; @@ -3422,7 +3491,7 @@ makeactualcall: } /* if (bptr -> flags >= BBREACHED) */ } /* for basic block */ - bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); + /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */ { /* generate bound check stubs */ @@ -3436,6 +3505,7 @@ makeactualcall: continue; } + gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos, xboundrefs->branchpos, (u1*) mcodeptr - mcodebase); diff --git a/comp/Makefile.in b/comp/Makefile.in index 66c7a976e..f238e75dd 100644 --- a/comp/Makefile.in +++ b/comp/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -71,8 +71,8 @@ SYSDEP_DIR = @SYSDEP_DIR@ 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 = @@ -82,13 +82,14 @@ DIST_COMMON = Makefile.am Makefile.in 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 @@ -101,75 +102,67 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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. diff --git a/config.h.in b/config.h.in index 448cad78b..f7f228304 100644 --- a/config.h.in +++ b/config.h.in @@ -38,6 +38,10 @@ #undef EXTERNAL_OVERFLOW #undef DONT_FREE_FIRST +/* Make automake happy */ +#undef PACKAGE +#undef VERSION + /* sysdep */ #undef SYSDEP_DIR @@ -87,10 +91,3 @@ /* Define if you have the m library (-lm). */ #undef HAVE_LIBM - -/* Name of package */ -#undef PACKAGE - -/* Version number of package */ -#undef VERSION - diff --git a/configure b/configure index 582882b6d..542742022 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #! /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 @@ -54,7 +54,6 @@ mandir='${prefix}/man' # 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 @@ -338,7 +337,7 @@ EOF 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-*) @@ -508,11 +507,9 @@ 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 -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 @@ -547,26 +544,26 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # 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/'` @@ -580,30 +577,28 @@ echo "$ac_t""$host" 1>&6 # 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" @@ -633,12 +628,13 @@ echo "$ac_t""$INSTALL" 1>&6 # 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 @@ -695,7 +691,7 @@ test "$program_suffix" != NONE && 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 @@ -741,7 +737,7 @@ EOF 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. @@ -754,7 +750,7 @@ else 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. @@ -767,7 +763,7 @@ else 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. @@ -780,7 +776,7 @@ else 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. @@ -793,7 +789,7 @@ else 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. @@ -850,16 +846,15 @@ EOF # 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" @@ -880,17 +875,16 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $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 @@ -925,61 +919,25 @@ else 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 <&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 @@ -993,24 +951,18 @@ else 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 @@ -1019,7 +971,7 @@ 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 @@ -1030,15 +982,11 @@ echo "$ac_t""$ac_cv_prog_gcc" 1>&6 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 @@ -1053,35 +1001,30 @@ rm -f conftest* 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" @@ -1101,7 +1044,7 @@ fi 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 @@ -1109,7 +1052,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lm $LIBS" cat > conftest.$ac_ext <&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 @@ -1153,12 +1096,12 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h 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 < #include <$ac_hdr> @@ -1166,7 +1109,7 @@ int main() { 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 @@ -1191,7 +1134,7 @@ done # 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 @@ -1199,7 +1142,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&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 @@ -1232,7 +1175,7 @@ fi 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 @@ -1240,7 +1183,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&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 @@ -1274,7 +1217,7 @@ fi 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= @@ -1289,14 +1232,14 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < 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 @@ -1306,31 +1249,14 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < 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 < -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 @@ -1342,8 +1268,6 @@ else fi rm -f conftest* fi -rm -f conftest* -fi rm -f conftest* ac_cv_prog_CPP="$CPP" fi @@ -1354,12 +1278,12 @@ 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 < #include @@ -1367,8 +1291,8 @@ else #include 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 @@ -1384,7 +1308,7 @@ rm -f conftest* 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 @@ -1402,7 +1326,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1423,7 +1347,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1434,7 +1358,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); 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 @@ -1461,18 +1385,18 @@ for ac_hdr in fcntl.h sys/time.h unistd.h 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 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" @@ -1499,12 +1423,12 @@ done 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 <&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 @@ -1574,21 +1498,21 @@ EOF 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 <&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 @@ -1614,12 +1538,12 @@ EOF 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 < #if STDC_HEADERS @@ -1628,7 +1552,7 @@ else #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 @@ -1647,12 +1571,12 @@ EOF 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 < #if STDC_HEADERS @@ -1661,7 +1585,7 @@ else #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 @@ -1680,12 +1604,12 @@ EOF 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 < #include @@ -1694,7 +1618,7 @@ int main() { 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 @@ -1715,12 +1639,12 @@ EOF 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 < #include @@ -1728,7 +1652,7 @@ int main() { 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 @@ -1751,13 +1675,13 @@ fi 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 < Autoconf TIOCGETP @@ -1775,7 +1699,7 @@ rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext < Autoconf TCGETA @@ -1797,7 +1721,7 @@ echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 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 @@ -1805,7 +1729,7 @@ else ac_cv_func_memcmp_clean=no else cat > conftest.$ac_ext <&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 @@ -1830,24 +1754,24 @@ fi 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 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" @@ -1875,12 +1799,12 @@ done 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 <&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 @@ -1928,7 +1852,7 @@ fi 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 @@ -1936,7 +1860,7 @@ else ac_cv_func_mmap_fixed_mapped=no else cat > conftest.$ac_ext <&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 @@ -2099,12 +2023,12 @@ EOF 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 < #include @@ -2121,7 +2045,7 @@ int main() { 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 @@ -2142,12 +2066,12 @@ EOF 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 <&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 @@ -2197,12 +2121,12 @@ done 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 < #ifdef MAP_FAILED @@ -2224,12 +2148,12 @@ fi 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 < #ifdef MAP_ANONYMOUS @@ -2281,7 +2205,7 @@ fi 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 @@ -2307,7 +2231,7 @@ EOF 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" @@ -2341,7 +2265,7 @@ EOF # 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 \). @@ -2408,7 +2332,7 @@ do 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 ;; @@ -2427,8 +2351,9 @@ trap 'rm -fr `echo "Makefile \ 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 < 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 @@ -2467,8 +2390,8 @@ s%@host_cpu@%$host_cpu%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 @@ -2536,8 +2459,9 @@ CONFIG_FILES=\${CONFIG_FILES-"Makefile \ alpha/Makefile \ mips/Makefile \ nat/Makefile \ + doc/Makefile \ comp/Makefile \ - doc/Makefile \ + narray/Makefile \ tst/Makefile "} EOF cat >> $CONFIG_STATUS <<\EOF diff --git a/doc/array.tex b/doc/array.tex new file mode 100644 index 000000000..b64068d2b --- /dev/null +++ b/doc/array.tex @@ -0,0 +1,375 @@ +\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} + + + + + + + + diff --git a/global.h b/global.h index 0cdf4817b..a5e7c0db8 100644 --- a/global.h +++ b/global.h @@ -12,7 +12,7 @@ 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 $ *******************************************************************************/ @@ -336,9 +336,27 @@ typedef struct fieldinfo {/* field of a class */ } 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) */ @@ -365,7 +383,8 @@ typedef struct methodinfo { /* method structure */ 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 */ diff --git a/jit.c b/jit.c index 989f4b741..7a69432a2 100644 --- a/jit.c +++ b/jit.c @@ -27,8 +27,15 @@ #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; @@ -41,6 +48,7 @@ bool checkbounds = true; bool checknull = true; bool checkfloats = true; bool checksync = true; +bool opt_loops = false; bool getcompilingtime = false; long compilingtime = 0; @@ -103,10 +111,6 @@ static int count_store_depth_init[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int *count_store_depth = count_store_depth_init; -/* include compiler data types ************************************************/ - -#include "jit/jitdef.h" - /* global compiler variables **************************************************/ @@ -124,7 +128,8 @@ static int maxlocals; /* maximal number of local JavaVM 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 */ @@ -140,6 +145,8 @@ static stackelement *stack; /* points to intermediate code instructions */ 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 */ @@ -154,9 +161,11 @@ static chain *uninitializedclasses; #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 */ @@ -181,9 +190,18 @@ methodptr compiler_compile (methodinfo *m); /* compile method with old compiler* 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) { @@ -249,7 +267,7 @@ methodptr jit_compile(methodinfo *m) jcodelength = m->jcodelength; jcode = m->jcode; exceptiontablelength = m->exceptiontablelength; - extable = m->exceptiontable; + raw_extable = m->exceptiontable; #ifdef STATISTICS count_tryblocks += exceptiontablelength; @@ -273,22 +291,60 @@ methodptr jit_compile(methodinfo *m) /* 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) @@ -299,8 +355,6 @@ methodptr jit_compile(methodinfo *m) if (showddatasegment) dseg_display((void*) (m->mcode)); - - /* release dump area */ dump_release (dumpsize); @@ -331,8 +385,7 @@ methodptr jit_compile(methodinfo *m) /* return pointer to the methods entry point */ return m -> entrypoint; -} - +} /* functions for compiler initialisation and finalisation *********************/ diff --git a/jit.h b/jit.h index aa52b03c7..3a34d92b7 100644 --- a/jit.h +++ b/jit.h @@ -26,6 +26,7 @@ extern bool showintermediate; /* generate intermediate code listing */ 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 */ diff --git a/jit/Makefile.in b/jit/Makefile.in index ab4de16fd..72b1e7948 100644 --- a/jit/Makefile.in +++ b/jit/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -81,13 +81,14 @@ DIST_COMMON = Makefile.am Makefile.in 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 @@ -100,75 +101,67 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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. diff --git a/jit/jitdef.h b/jit/jitdef.h index c55fc994f..5691143c6 100644 --- a/jit/jitdef.h +++ b/jit/jitdef.h @@ -80,6 +80,10 @@ struct instruction { 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 */ }; @@ -108,6 +112,14 @@ struct basicblock { 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; + }; diff --git a/jit/mcode.c b/jit/mcode.c index 19d43519c..638101d44 100644 --- a/jit/mcode.c +++ b/jit/mcode.c @@ -323,9 +323,9 @@ static void mcode_finish(int mcodelen) 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; + } } diff --git a/jit/parse.c b/jit/parse.c index f9860e08c..958068eb3 100644 --- a/jit/parse.c +++ b/jit/parse.c @@ -8,7 +8,7 @@ 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 $ *******************************************************************************/ @@ -288,7 +288,7 @@ static void parse() /* 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) */ @@ -305,19 +305,34 @@ static void parse() /* 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 @@ -1066,6 +1081,7 @@ static void parse() 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 */ @@ -1076,37 +1092,69 @@ static void parse() 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]; + } } } diff --git a/jit/reg.c b/jit/reg.c index 1f9445b2d..09bd3ad8a 100644 --- a/jit/reg.c +++ b/jit/reg.c @@ -257,6 +257,7 @@ static void interface_regalloc () 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) { @@ -335,11 +336,13 @@ static void interface_regalloc () } /* if (type >= 0) */ } /* for t */ } /* for s */ + maxmemuse = ifmemuse; maxtmpintreguse = iftmpintregcnt; maxsavintreguse = ifsavintregcnt; maxtmpfltreguse = iftmpfltregcnt; maxsavfltreguse = ifsavfltregcnt; + } @@ -595,18 +598,22 @@ static void allocate_scratch_registers() 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 */ @@ -1000,7 +1007,7 @@ static void allocate_scratch_registers() iptr++; } /* while instructions */ } /* if */ - bptr++; + bptr = bptr->next; } /* while blocks */ } diff --git a/jit/stack.c b/jit/stack.c index 17ee4ed81..dd9fc35dd 100644 --- a/jit/stack.c +++ b/jit/stack.c @@ -17,7 +17,7 @@ #else #define COUNT(cnt) #endif - + #define STACKRESET {curstack=0;stackdepth=0;} #define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");} @@ -164,7 +164,9 @@ static void analyse_stack() int superblockend, repeat, deadcode; instruction *iptr = instr; basicblock *bptr, *tbptr; - s4 *s4ptr; + s4 *s4ptr; + void* *tptr; + xtable *ex; arguments_num = 0; new = stack; @@ -290,6 +292,7 @@ static void analyse_stack() b_index = bptr - block; while (--len >= 0) { opcode = iptr->opc; + iptr->target = NULL; switch (opcode) { /* pop 0 push 0 */ @@ -472,6 +475,9 @@ icmd_if_icmp_tail: /* 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; @@ -656,6 +662,9 @@ icmd_lconst_lcmp_tail: 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); @@ -858,6 +867,9 @@ icmd_lconst_lcmp_tail: COUNT(count_pcmd_bra); OP1_0(TYPE_ADR); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); break; @@ -927,6 +939,9 @@ icmd_lconst_lcmp_tail: #endif OP1_0(TYPE_INT); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); break; @@ -935,6 +950,9 @@ icmd_lconst_lcmp_tail: case ICMD_GOTO: COUNT(count_pcmd_bra); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); SETDST; superblockend = true; @@ -950,8 +968,19 @@ icmd_lconst_lcmp_tail: 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; @@ -967,8 +996,19 @@ icmd_lconst_lcmp_tail: 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; } @@ -994,6 +1034,9 @@ icmd_lconst_lcmp_tail: COUNT(count_pcmd_bra); OP2_0(TYPE_INT); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); break; @@ -1002,6 +1045,9 @@ icmd_lconst_lcmp_tail: COUNT(count_pcmd_bra); OP2_0(TYPE_ADR); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); break; @@ -1201,6 +1247,9 @@ icmd_lcmp_if_tail: /* 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; @@ -1342,6 +1391,9 @@ icmd_lcmp_if_tail: 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; @@ -1467,8 +1519,8 @@ builtin2: 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) @@ -1658,11 +1710,14 @@ static char *jit_type[] = { 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("."); @@ -1672,11 +1727,11 @@ static void show_icmd_method() 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"); @@ -1735,19 +1790,20 @@ static void show_icmd_method() 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--) @@ -1814,6 +1870,28 @@ static void show_icmd_method() 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: @@ -1906,7 +1984,7 @@ static void show_icmd_method() 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: @@ -1926,25 +2004,39 @@ static void show_icmd_method() 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; } @@ -1953,15 +2045,26 @@ static void show_icmd_method() 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"); @@ -1970,6 +2073,7 @@ static void show_icmd_method() } printf("\n"); } + */ } diff --git a/main.c b/main.c index fd2ad9794..e47a1098c 100644 --- a/main.c +++ b/main.c @@ -17,7 +17,7 @@ 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 $ *******************************************************************************/ @@ -89,6 +89,7 @@ void **stackbottom = 0; #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}, @@ -121,6 +122,7 @@ struct {char *name; bool arg; int value;} opts[] = { {"gc1", false, OPT_GC1}, {"gc2", false, OPT_GC2}, #endif + {"oloop", false, OPT_OLOOP}, {NULL, false, 0} }; @@ -198,6 +200,7 @@ static void print_usage() 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 @@ -675,6 +678,10 @@ int main(int argc, char **argv) } break; + case OPT_OLOOP: + opt_loops = true; + break; + default: print_usage(); exit(10); diff --git a/mips/Makefile.in b/mips/Makefile.in index 2479c5a6f..6a49b83e4 100644 --- a/mips/Makefile.in +++ b/mips/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -71,8 +71,8 @@ SYSDEP_DIR = @SYSDEP_DIR@ 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 = @@ -82,13 +82,14 @@ DIST_COMMON = Makefile.am Makefile.in 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 @@ -101,75 +102,67 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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. diff --git a/mm/Makefile.in b/mm/Makefile.in index 8c8dc9f0e..e6422d653 100644 --- a/mm/Makefile.in +++ b/mm/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -73,11 +73,14 @@ VERSION = @VERSION@ 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 = @@ -94,26 +97,28 @@ libmm_old_a_LIBADD = 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 @@ -127,9 +132,6 @@ distclean-noinstLIBRARIES: maintainer-clean-noinstLIBRARIES: -.c.o: - $(COMPILE) -c $< - .s.o: $(COMPILE) -c $< @@ -159,12 +161,8 @@ libmm_old.a: $(libmm_old_a_OBJECTS) $(libmm_old_a_DEPENDENCIES) 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=; \ @@ -190,84 +188,102 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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. diff --git a/narray/analyze.c b/narray/analyze.c new file mode 100644 index 000000000..42444c529 --- /dev/null +++ b/narray/analyze.c @@ -0,0 +1,3564 @@ +/* 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; itoOpt); + printf("Modified Vars: "); + /* + for (i=0; inum_vars; ++i) + printf("%d ", lc->vars[i]); + printf("\n\n"); + */ + lc = lc->next; + } + + printf("\nNested Loops:\n"); + for (i=0; iloop_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 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; iopc) { + 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; iopc) { + 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; knodes; + 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>=(b+1) */ + if (left->constant != 0) + left->constant -= 1; + else + right->constant += 1; + } + else + operand = OP_LT; /* a a ... */ + case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */ + if (changed) + operand = OP_LT; /* b>a -> ab -> 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; cntcopied_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; itype) + { + + /* 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; ilower_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; ilower_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; ilower_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; iopc) { + 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; ichanges = 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: + */ + + + diff --git a/narray/graph.c b/narray/graph.c new file mode 100644 index 000000000..c13844ad0 --- /dev/null +++ b/narray/graph.c @@ -0,0 +1,401 @@ +/* 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; ivalue); + 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: + */ diff --git a/narray/loop.c b/narray/loop.c new file mode 100644 index 000000000..7d1a486c7 --- /dev/null +++ b/narray/loop.c @@ -0,0 +1,293 @@ +/* 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; i0; --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 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; jsecond 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; inext = 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; ivalue)) + 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: + */ + + + diff --git a/narray/loop.h b/narray/loop.h new file mode 100644 index 000000000..962e6349b --- /dev/null +++ b/narray/loop.h @@ -0,0 +1,343 @@ +/* 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: + */ + diff --git a/narray/tracing.c b/narray/tracing.c new file mode 100644 index 000000000..e963346cc --- /dev/null +++ b/narray/tracing.c @@ -0,0 +1,647 @@ +/* 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: + */ diff --git a/nat/Makefile.in b/nat/Makefile.in index bc093f63d..6f50fff21 100644 --- a/nat/Makefile.in +++ b/nat/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -81,13 +81,14 @@ DIST_COMMON = Makefile.am Makefile.in 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 @@ -100,75 +101,67 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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. diff --git a/src/cacao/cacao.c b/src/cacao/cacao.c index 30534360c..82ce1e078 100644 --- a/src/cacao/cacao.c +++ b/src/cacao/cacao.c @@ -17,7 +17,7 @@ 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 $ *******************************************************************************/ @@ -89,6 +89,7 @@ void **stackbottom = 0; #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}, @@ -121,6 +122,7 @@ struct {char *name; bool arg; int value;} opts[] = { {"gc1", false, OPT_GC1}, {"gc2", false, OPT_GC2}, #endif + {"oloop", false, OPT_OLOOP}, {NULL, false, 0} }; @@ -198,6 +200,7 @@ static void print_usage() 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 @@ -675,6 +678,10 @@ int main(int argc, char **argv) } break; + case OPT_OLOOP: + opt_loops = true; + break; + default: print_usage(); exit(10); diff --git a/src/vm/global.h b/src/vm/global.h index 0cdf4817b..a5e7c0db8 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -12,7 +12,7 @@ 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 $ *******************************************************************************/ @@ -336,9 +336,27 @@ typedef struct fieldinfo {/* field of a class */ } 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) */ @@ -365,7 +383,8 @@ typedef struct methodinfo { /* method structure */ 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 */ diff --git a/src/vm/jit/parse.c b/src/vm/jit/parse.c index f9860e08c..958068eb3 100644 --- a/src/vm/jit/parse.c +++ b/src/vm/jit/parse.c @@ -8,7 +8,7 @@ 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 $ *******************************************************************************/ @@ -288,7 +288,7 @@ static void parse() /* 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) */ @@ -305,19 +305,34 @@ static void parse() /* 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 @@ -1066,6 +1081,7 @@ static void parse() 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 */ @@ -1076,37 +1092,69 @@ static void parse() 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]; + } } } diff --git a/src/vm/jit/stack.c b/src/vm/jit/stack.c index 17ee4ed81..dd9fc35dd 100644 --- a/src/vm/jit/stack.c +++ b/src/vm/jit/stack.c @@ -17,7 +17,7 @@ #else #define COUNT(cnt) #endif - + #define STACKRESET {curstack=0;stackdepth=0;} #define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");} @@ -164,7 +164,9 @@ static void analyse_stack() int superblockend, repeat, deadcode; instruction *iptr = instr; basicblock *bptr, *tbptr; - s4 *s4ptr; + s4 *s4ptr; + void* *tptr; + xtable *ex; arguments_num = 0; new = stack; @@ -290,6 +292,7 @@ static void analyse_stack() b_index = bptr - block; while (--len >= 0) { opcode = iptr->opc; + iptr->target = NULL; switch (opcode) { /* pop 0 push 0 */ @@ -472,6 +475,9 @@ icmd_if_icmp_tail: /* 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; @@ -656,6 +662,9 @@ icmd_lconst_lcmp_tail: 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); @@ -858,6 +867,9 @@ icmd_lconst_lcmp_tail: COUNT(count_pcmd_bra); OP1_0(TYPE_ADR); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); break; @@ -927,6 +939,9 @@ icmd_lconst_lcmp_tail: #endif OP1_0(TYPE_INT); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); break; @@ -935,6 +950,9 @@ icmd_lconst_lcmp_tail: case ICMD_GOTO: COUNT(count_pcmd_bra); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); SETDST; superblockend = true; @@ -950,8 +968,19 @@ icmd_lconst_lcmp_tail: 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; @@ -967,8 +996,19 @@ icmd_lconst_lcmp_tail: 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; } @@ -994,6 +1034,9 @@ icmd_lconst_lcmp_tail: COUNT(count_pcmd_bra); OP2_0(TYPE_INT); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); break; @@ -1002,6 +1045,9 @@ icmd_lconst_lcmp_tail: COUNT(count_pcmd_bra); OP2_0(TYPE_ADR); tbptr = block + block_index[iptr->op1]; + + iptr[0].target = (void *) tbptr; + MARKREACHED(tbptr, copy); break; @@ -1201,6 +1247,9 @@ icmd_lcmp_if_tail: /* 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; @@ -1342,6 +1391,9 @@ icmd_lcmp_if_tail: 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; @@ -1467,8 +1519,8 @@ builtin2: 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) @@ -1658,11 +1710,14 @@ static char *jit_type[] = { 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("."); @@ -1672,11 +1727,11 @@ static void show_icmd_method() 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"); @@ -1735,19 +1790,20 @@ static void show_icmd_method() 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--) @@ -1814,6 +1870,28 @@ static void show_icmd_method() 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: @@ -1906,7 +1984,7 @@ static void show_icmd_method() 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: @@ -1926,25 +2004,39 @@ static void show_icmd_method() 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; } @@ -1953,15 +2045,26 @@ static void show_icmd_method() 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"); @@ -1970,6 +2073,7 @@ static void show_icmd_method() } printf("\n"); } + */ } diff --git a/tests/Makefile.in b/tests/Makefile.in index 49aa1e8d0..2b30d9c95 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -81,13 +81,14 @@ DIST_COMMON = Makefile.am Makefile.in 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 @@ -100,75 +101,67 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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: diff --git a/tests/jctest.java b/tests/jctest.java index 5ba14eecf..b08880884 100644 --- a/tests/jctest.java +++ b/tests/jctest.java @@ -432,7 +432,6 @@ public class jctest implements jcinterface { // ************************ test array bounds ****************************** public static void testarraybounds(byte[] ba, int i) { - p ("testarraybounds: " + (i - 10)); ba[i-10] = 0; p ("testarraybounds: " + (i - 5)); @@ -442,7 +441,7 @@ public class jctest implements jcinterface { p ("testarraybounds: " + (i + 5)); ba[i+5] = 0; p ("testarraybounds: " + (i + 10)); - ba[i+10] = 0; + ba[i+10] = 0; } @@ -494,7 +493,7 @@ public class jctest implements jcinterface { 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"); @@ -502,63 +501,68 @@ public class jctest implements jcinterface { 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; @@ -588,7 +592,7 @@ public class jctest implements jcinterface { 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"); @@ -596,12 +600,13 @@ public class jctest implements jcinterface { 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"); @@ -818,9 +823,8 @@ public class jctest implements jcinterface { } } } + - - } diff --git a/threads/Makefile.in b/threads/Makefile.in index 200bb05ed..6b8cc2667 100644 --- a/threads/Makefile.in +++ b/threads/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -74,10 +74,11 @@ VERSION = @VERSION@ 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 = @@ -92,26 +93,27 @@ libthreads_a_LIBADD = 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 @@ -125,9 +127,6 @@ distclean-noinstLIBRARIES: maintainer-clean-noinstLIBRARIES: -.c.o: - $(COMPILE) -c $< - .s.o: $(COMPILE) -c $< @@ -152,12 +151,8 @@ libthreads.a: $(libthreads_a_OBJECTS) $(libthreads_a_DEPENDENCIES) 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=; \ @@ -183,84 +178,102 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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. diff --git a/toolbox/Makefile.in b/toolbox/Makefile.in index c76ca7024..898911f64 100644 --- a/toolbox/Makefile.in +++ b/toolbox/Makefile.in @@ -1,6 +1,6 @@ -# 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. @@ -11,7 +11,7 @@ # PARTICULAR PURPOSE. -SHELL = @SHELL@ +SHELL = /bin/sh srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -32,7 +32,7 @@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include -DESTDIR = +DISTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -46,7 +46,7 @@ AUTOMAKE = @AUTOMAKE@ 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@ @@ -73,10 +73,13 @@ VERSION = @VERSION@ 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 = @@ -91,26 +94,28 @@ libtoolbox_a_LIBADD = 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 @@ -124,9 +129,6 @@ distclean-noinstLIBRARIES: maintainer-clean-noinstLIBRARIES: -.c.o: - $(COMPILE) -c $< - .s.o: $(COMPILE) -c $< @@ -151,12 +153,8 @@ libtoolbox.a: $(libtoolbox_a_OBJECTS) $(libtoolbox_a_DEPENDENCIES) 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=; \ @@ -182,84 +180,102 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) 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. -- 2.25.1