Initial revision
authorChristian Schäfer <schaefer@ipd.info.uni-karlsruhe.de>
Tue, 16 May 2000 16:03:36 +0000 (16:03 +0000)
committerChristian Schäfer <schaefer@ipd.info.uni-karlsruhe.de>
Tue, 16 May 2000 16:03:36 +0000 (16:03 +0000)
[r4]

95 files changed:
Makefile [new file with mode: 0644]
ir/Makefile [new file with mode: 0644]
ir/adt/ABSTRACT_DATATYPES [new file with mode: 0644]
ir/adt/Makefile [new file with mode: 0644]
ir/adt/array.c [new file with mode: 0644]
ir/adt/array.h [new file with mode: 0644]
ir/adt/cookies.h [new file with mode: 0644]
ir/adt/host.h [new file with mode: 0644]
ir/adt/obst.h [new file with mode: 0644]
ir/adt/pdeq.c [new file with mode: 0644]
ir/adt/pdeq.h [new file with mode: 0644]
ir/adt/pset.h [new file with mode: 0644]
ir/adt/set.c [new file with mode: 0644]
ir/adt/set.h [new file with mode: 0644]
ir/adt/xmalloc.c [new file with mode: 0644]
ir/common/Makefile [new file with mode: 0644]
ir/common/common.c [new file with mode: 0644]
ir/common/common.h [new file with mode: 0644]
ir/common/firm.c [new file with mode: 0644]
ir/common/firm.h [new file with mode: 0644]
ir/common/misc.h [new file with mode: 0644]
ir/common/panic.c [new file with mode: 0644]
ir/common/panic.h [new file with mode: 0644]
ir/common/strerror.c [new file with mode: 0644]
ir/common/tune.h [new file with mode: 0644]
ir/common/xfprintf.c [new file with mode: 0644]
ir/common/xgprintf.c [new file with mode: 0644]
ir/common/xoprintf.c [new file with mode: 0644]
ir/common/xp_help.h [new file with mode: 0644]
ir/common/xprintf.h [new file with mode: 0644]
ir/debug/Makefile [new file with mode: 0644]
ir/debug/debug.c [new file with mode: 0644]
ir/debug/debug.h [new file with mode: 0644]
ir/ident/Makefile [new file with mode: 0644]
ir/ident/ident.c [new file with mode: 0644]
ir/ident/ident.h [new file with mode: 0644]
ir/ident/xx_ident.h [new file with mode: 0644]
ir/ir/INTERMEDIATE_REPRESENTATION [new file with mode: 0644]
ir/ir/Makefile [new file with mode: 0644]
ir/ir/ircons.c [new file with mode: 0644]
ir/ir/ircons.h [new file with mode: 0644]
ir/ir/ircons.h.flc [new file with mode: 0644]
ir/ir/irdump.c [new file with mode: 0644]
ir/ir/irdump.h [new file with mode: 0644]
ir/ir/irflag.c [new file with mode: 0644]
ir/ir/irflag.h [new file with mode: 0644]
ir/ir/irgmod.c [new file with mode: 0644]
ir/ir/irgmod.h [new file with mode: 0644]
ir/ir/irgraph.c [new file with mode: 0644]
ir/ir/irgraph.h [new file with mode: 0644]
ir/ir/irgwalk.c [new file with mode: 0644]
ir/ir/irgwalk.h [new file with mode: 0644]
ir/ir/irmode.c [new file with mode: 0644]
ir/ir/irmode.h [new file with mode: 0644]
ir/ir/irnode.c [new file with mode: 0644]
ir/ir/irnode.h [new file with mode: 0644]
ir/ir/irop.c [new file with mode: 0644]
ir/ir/irop.h [new file with mode: 0644]
ir/ir/iropt.c [new file with mode: 0644]
ir/ir/iropt.c.flc [new file with mode: 0644]
ir/ir/iropt.h [new file with mode: 0644]
ir/ir/irvrfy.c [new file with mode: 0644]
ir/ir/irvrfy.h [new file with mode: 0644]
ir/tr/Makefile [new file with mode: 0644]
ir/tr/TYPE_REPRESENTATION [new file with mode: 0644]
ir/tr/entity.c [new file with mode: 0644]
ir/tr/entity.h [new file with mode: 0644]
ir/tr/mangle.c [new file with mode: 0644]
ir/tr/mangle.h [new file with mode: 0644]
ir/tr/type.c [new file with mode: 0644]
ir/tr/type.h [new file with mode: 0644]
ir/tr/type_or_entity.h [new file with mode: 0644]
ir/tr/typewalk.c [new file with mode: 0644]
ir/tr/typewalk.h [new file with mode: 0644]
ir/tv/Makefile [new file with mode: 0644]
ir/tv/ieee754.h [new file with mode: 0644]
ir/tv/label.c [new file with mode: 0644]
ir/tv/label.h [new file with mode: 0644]
ir/tv/tv.c [new file with mode: 0644]
ir/tv/tv.h [new file with mode: 0644]
testprograms/Makefile [new file with mode: 0644]
testprograms/array-heap_example.c [new file with mode: 0644]
testprograms/array-stack_example.c [new file with mode: 0644]
testprograms/call_str_example.c [new file with mode: 0644]
testprograms/cond_example.c [new file with mode: 0644]
testprograms/const_eval_example.c [new file with mode: 0644]
testprograms/dead_block_example.c [new file with mode: 0644]
testprograms/empty.c [new file with mode: 0644]
testprograms/if_else_example.c [new file with mode: 0644]
testprograms/if_example.c [new file with mode: 0644]
testprograms/if_while_example.c [new file with mode: 0644]
testprograms/irr_cf_example.c [new file with mode: 0644]
testprograms/irr_loop_example.c [new file with mode: 0644]
testprograms/memory_example.c [new file with mode: 0644]
testprograms/oo_program_example.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..a685163
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,38 @@
+# Hey, emacs, this is a -*- makefile -*-
+#
+# Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Main Makefile
+
+# This makefile makes firm and/or the testprograms.
+
+SUBDIRS = ir testprograms
+
+MAKE    = /usr/bin/make -k
+SHELL   = /bin/sh
+
+.PHONY: default all clean realclean install depend ir testprograms
+
+
+
+ir:
+       $(MAKE) -C ir
+
+all:   TAGS ir testprograms
+
+testprograms:
+       $(MAKE) -C testprograms
+
+clean:
+       for i in $(SUBDIRS); do  $(MAKE) -C $$i clean; done
+
+realclean:
+       for i in $(SUBDIRS); do  $(MAKE) -C $$i realclean; done
+       rm -f libfirm.a core
+
+TAGFILES = $(shell find . -name '*.c' -o -name '*.h')
+
+TAGS:   $(TAGFILES)
+       etags -C $(TAGFILES)
diff --git a/ir/Makefile b/ir/Makefile
new file mode 100644 (file)
index 0000000..12ca79c
--- /dev/null
@@ -0,0 +1,66 @@
+# Hey, emacs, this is a -*- makefile -*-
+#
+# Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Makefile for IR library.
+
+# This makefile descends to all directories listed in INCLUDES and to
+# testprograms and calls make with the corresponding target there.
+# After returning it builds a library out of the firm files.
+# Further it updates the TAGS file with each recompilation
+
+SUBDIRS = adt common debug ident ir tr tv
+INCLUDES = -I../adt -I../common -I../debug -I../ident -I../include \
+          -I../ir -I../tr -I../tv
+OFILES =
+
+AR          = ar rcs
+
+MAKE    = /usr/bin/make -k
+SHELL   = /bin/sh
+
+CXX         = gcc
+CFLAGS      = -pipe -Wall #-ansi -pedantic # -g
+COPTFLAGS   = -O3 -ffast-math # -fno-caller-saves
+
+TARGET = libfirm.a
+
+.PHONY: default all clean realclean install depend $(TARGET)
+
+$(TARGET):
+#      mkdir objects
+       for i in $(SUBDIRS); do $(MAKE) "INCLUDES=$(INCLUDES)" -C $$i; done
+       $(AR) $(TARGET) objects/*.o
+       mv $(TARGET) ..
+
+debug:
+       for i in $(SUBDIRS); do $(MAKE) "CFLAGS=$(CFLAGS) -g INCLUDES=$(INCLUDES)" -C $$i; done
+
+all:   TAGS $(TARGET)
+
+#testprograms:
+#      $(MAKE) -C testprograms
+
+clean:
+       for i in $(SUBDIRS); do  $(MAKE) -C $$i clean; done
+
+realclean:
+       for i in $(SUBDIRS); do  $(MAKE) -C $$i realclean; done
+       $(MAKE) -C testprograms realclean
+       rm -f $(TARGET) core
+
+profile:        realclean
+       for i in $(SUBDIRS); do  \
+                        $(MAKE) \
+                        "CXX=$(CXX)" \
+                        "CFLAGS=-g -pg" \
+                       "INCLUDES=$(INCLUDES)" -C $$i; \
+        done
+
+
+TAGFILES = $(shell find . -name '*.c' -o -name '*.h')
+
+TAGS:   $(TAGFILES)
+       etags -C $(TAGFILES)
diff --git a/ir/adt/ABSTRACT_DATATYPES b/ir/adt/ABSTRACT_DATATYPES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ir/adt/Makefile b/ir/adt/Makefile
new file mode 100644 (file)
index 0000000..5d6bed7
--- /dev/null
@@ -0,0 +1,65 @@
+# Hey, emacs, this is a -*- makefile -*-
+## Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Makefile for adt -- abstract data types
+
+CXX         = gcc
+CFLAGS      = -pipe -Wall # -ansi -pedantic
+CXXFLAGS    = # -g
+COPTFLAGS   = -O3
+LDFLAGS     =
+DEPENDFLAGS = -M
+LIBPATH     =
+LIBS        =
+X_LIBS      =
+INCLUDES    = -I../adt -I../common -I../debug
+X_INCLUDES  =
+
+SHELL       = /bin/sh
+MAKE        = /usr/bin/make
+
+MEMBERS         = array.m pdeq.m set.m
+
+CFILES = $(MEMBERS:.m=.c)
+CFIMES +=  xmalloc.c
+
+HFILES = $(MEMBERS:.m=.h)
+HFILES +=  cookies.h host.h obst.h pset.h
+HFILES +=  misc.h tune.h debug.h
+
+OFILES = $(MEMBERS:%.m=../objects/%.o)
+OFILES += ../objects/xmalloc.o ../objects/pset.o
+
+DFILES = $(MEMBERS:.m=.d)
+
+TARGET = all
+
+.PHONY: default all clean realclean install depend
+.SUFFIXES: .d .h .c .o
+.DEFAULT: $(TARGET)
+.SILENT: $(DFILES) clean  # hides output
+
+$(TARGET): $(DFILES) $(OFILES)
+
+%.d:    %.c
+       $(SHELL) -ec '$(CXX) $(DEPENDFLAGS) $(INCLUDES) $(X_INCLUDES) $< | sed '\''s/\($*\)\.o[ :]*/\.\.\/objects\/\1.o $@ : /g'\'' > $@'
+
+
+../objects/%.o:    %.c
+       $(CXX) $(CFLAGS) $(CXXFLAGS) $(COPTFLAGS) $(INCLUDES) $(X_INCLUDES) -c $< -o $@
+
+# a hack to force recompilation
+../objects/pset.o : set.c pset.h ../objects/set.o
+       $(COMPILE.c) $(INCLUDES) -DPSET -o $@ $<
+#      $(CXX) $(CFLAGS) $(CXXFLAGS) $(COPTFLAGS) $(INCLUDES) $(X_INCLUDES) -c $< -o $@
+
+clean:
+       rm -f $(OFILES) $(DFILES)
+
+realclean:     clean
+       rm -f $(TARGET) *.flc TAGS
+
+
+-include $(DFILES)
diff --git a/ir/adt/array.c b/ir/adt/array.c
new file mode 100644 (file)
index 0000000..4e95406
--- /dev/null
@@ -0,0 +1,111 @@
+/* Array --- dynamic & flexible arrays.
+   Copyright (C) 1995, 1996 Markus Armbruster
+   All rights reserved. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include "array.h"
+
+/* Undefine the macros to get the functions instead, cf tmalloc.c.  */
+#undef xmalloc
+#undef xrealloc
+#undef xstrdup
+#undef xfree
+
+
+_arr_descr arr_mt_descr
+#ifndef NDEBUG
+  = { ARR_D_MAGIC }
+#endif
+;
+
+void *
+_new_arr_d (struct obstack *obstack, int nelts, size_t elts_size)
+{
+  _arr_descr *new;
+
+  assert (obstack && (nelts >= 0));
+
+  new = obstack_alloc (obstack, _ARR_ELTS_OFFS+elts_size);
+  _ARR_SET_DBGINF (new, ARR_D_MAGIC, elts_size/nelts);
+  new->u.obstack = obstack;
+  new->nelts = nelts;
+  return new->v.elts;
+}
+
+
+void *
+_new_arr_f (int nelts, size_t elts_size)
+{
+  _arr_descr *new;
+
+  assert (nelts >= 0);
+  new = xmalloc (_ARR_ELTS_OFFS+elts_size);
+  _ARR_SET_DBGINF (new, ARR_F_MAGIC, nelts ? elts_size/nelts : 0);
+  new->u.allocated = new->nelts = nelts;
+  return new->v.elts;
+}
+
+
+void
+_del_arr_f (void *elts)
+{
+  _arr_descr *dp = _ARR_DESCR (elts);
+
+  ARR_VRFY (elts);
+  assert (dp->cookie == ARR_F_MAGIC);
+
+#ifndef NDEBUG
+  dp->cookie = 0xdeadbeef;
+#endif
+  free (dp);
+}
+
+
+void *
+_arr_setlen (void *elts, int nelts, size_t elts_size)
+{
+  _arr_descr *dp = _ARR_DESCR (elts);
+
+  assert ((dp->cookie == ARR_F_MAGIC) && (nelts >= 0));
+  ARR_VRFY (elts);
+  assert (!dp->eltsize || !nelts || (dp->eltsize == elts_size/nelts));
+
+  dp = xrealloc (dp, _ARR_ELTS_OFFS+elts_size);
+  dp->u.allocated = dp->nelts = nelts;
+
+  return dp->v.elts;
+}
+
+
+void *
+_arr_resize (void *elts, int nelts, size_t eltsize)
+{
+  _arr_descr *dp = _ARR_DESCR (elts);
+  int n;
+
+  assert ((dp->cookie == ARR_F_MAGIC) && (nelts >= 0));
+  ARR_VRFY (elts);
+  assert (dp->eltsize ? dp->eltsize == eltsize : (dp->eltsize = eltsize, 1));
+
+  /* @@@ lots of resizes for small nelts */
+  n = MAX (1, dp->u.allocated);
+  while (nelts > n) n <<= 1;
+  while (3*nelts < n) n >>= 1;
+  assert (n >= nelts);
+
+  if (n != dp->u.allocated) {
+    dp = xrealloc (dp, _ARR_ELTS_OFFS+eltsize*n);
+    dp->u.allocated = n;
+#if defined(DEBUG) && defined(HAVE_GNU_MALLOC)
+  } else {
+    tmalloc_tag = NULL;
+#endif
+  }
+  dp->nelts = nelts;
+
+  return dp->v.elts;
+}
diff --git a/ir/adt/array.h b/ir/adt/array.h
new file mode 100644 (file)
index 0000000..11c0be6
--- /dev/null
@@ -0,0 +1,139 @@
+/* Declarations for Array.
+   Copyright (C) 1995, 1996 Markus Armbruster
+   All rights reserved. */
+
+/* @@@ growing a dynamic on an obstack */
+
+#ifndef _ARRAY_H
+#define _ARRAY_H
+
+#include <assert.h>
+#include <stddef.h>
+#include <obstack.h>
+#include "cookies.h"
+#include "misc.h"
+
+
+/* Flexible create / delete */
+#define NEW_ARR_F(type, nelts)                                         \
+  (XMALLOC_TRACE (type *)_new_arr_f ((nelts), sizeof(type) * (nelts)))
+#define CLONE_ARR_F(type, arr)                 \
+  NEW_ARR_F (type, ARR_LEN ((arr)))
+#define DUP_ARR_F(type, arr)                                                   \
+  memcpy (CLONE_ARR_F (type, (arr)), (arr), sizeof(type) * ARR_LEN((arr)))
+#define DEL_ARR_F(arr) (XMALLOC_TRACE _del_arr_f ((arr)))
+
+/* Dynamic create on obstacks */
+#define NEW_ARR_D(type, obstack, nelts)                                        \
+  (  nelts                                                             \
+   ? (type *)_new_arr_d ((obstack), (nelts), sizeof(type) * (nelts))   \
+   : (type *)arr_mt_descr.v.elts)
+#define CLONE_ARR_D(type, obstack, arr)                \
+  NEW_ARR_D (type, (obstack), ARR_LEN ((arr)))
+#define DUP_ARR_D(type, obstack, arr)                                                  \
+  memcpy (CLONE_ARR_D (type, (obstack), (arr)), (arr), sizeof(type) * ARR_LEN ((arr)))
+
+/* Automatic create; delete is automatic at return from function */
+/* Quick'n'dirty! */
+#define NEW_ARR_A(type, var, n)                                                                        \
+  do {                                                                                         \
+    int _nelts = (n);                                                                          \
+    assert (_nelts >= 0);                                                                      \
+    (var) = (void *)((_arr_descr *)alloca (_ARR_ELTS_OFFS + sizeof(type) * _nelts))->v.elts;   \
+    _ARR_SET_DBGINF (_ARR_DESCR ((var)), ARR_A_MAGIC, sizeof (type));                          \
+    (void)(_ARR_DESCR ((var))->nelts = _nelts);                                                        \
+  } while (0)
+#define CLONE_ARR_A(type, var, arr)            \
+  NEW_ARR_A (type, (var), ARR_LEN ((arr)))
+
+#define DUP_ARR_A(type, var, arr)                                      \
+  do { CLONE_ARR_A(type, (var), (arr));                                        \
+       memcpy ((var), (arr), sizeof (type) * ARR_LEN ((arr))); }       \
+  while (0)
+
+/* Declare an initialized array of fixed size */
+#define DECL_ARR_S(type, var, _nelts)                                  \
+  ARR_STRUCT(type, (_nelts) ? (_nelts) : 1) _##var;                    \
+  type *var = (_ARR_SET_DBGINF (&_##var, ARR_A_MAGIC, sizeof (type)),  \
+              _##var.nelts = _nelts,                                   \
+              _##var.v.elts)
+
+/* Length */
+#define ARR_LEN(arr) (ARR_VRFY ((arr)), _ARR_DESCR((arr))->nelts)
+
+/* Resize
+   Applicable to flexibles only, change arr which must be an lvalue.  */
+/* resize arr to hold n elts */
+#define ARR_RESIZE(type, arr, n)                                       \
+  (XMALLOC_TRACE (arr) = _arr_resize ((arr), (n), sizeof(type)))
+/* resize arr to hold exactly n elts */
+#define ARR_SETLEN(type, arr, n)                                       \
+  (XMALLOC_TRACE (arr) = _arr_setlen ((arr), (n), sizeof(type) * (n)))
+/* resize arr by delta elts */
+#define ARR_EXTEND(type, arr, delta)                   \
+  ARR_RESIZE (type, (arr), ARR_LEN ((arr)) + (delta))
+/* resize arr to hold n elts only if it is currently shorter */
+#define ARR_EXTO(type, arr, n)                                         \
+  ((n) >= ARR_LEN ((arr)) ? ARR_RESIZE (type, (arr), (n)+1) : (arr))
+/* append one elt to arr */
+#define ARR_APP1(type, arr, elt)                                       \
+  (ARR_EXTEND (type, (arr), 1), (arr)[ARR_LEN ((arr))-1] = (elt))
+
+
+#ifdef NDEBUG
+# define ARR_VRFY(arr) ((void)0)
+# define ARR_IDX_VRFY(arr, idx) ((void)0)
+#else
+# define ARR_VRFY(arr)                                                                 \
+    assert (   (   (_ARR_DESCR((arr))->cookie == ARR_D_MAGIC)                          \
+               || (_ARR_DESCR((arr))->cookie == ARR_A_MAGIC)                           \
+               || (_ARR_DESCR((arr))->cookie == ARR_F_MAGIC))                          \
+           && (   (_ARR_DESCR((arr))->cookie != ARR_F_MAGIC)                           \
+               || (_ARR_DESCR((arr))->u.allocated >= _ARR_DESCR((arr))->nelts))        \
+           && (_ARR_DESCR((arr))->nelts >= 0))
+# define ARR_IDX_VRFY(arr, idx)                                \
+    assert ((0 <= (idx)) && ((idx) < ARR_LEN ((arr))))
+#endif
+
+
+/* Private */
+/* Don't try this at home, kids, we're trained professionals ;-> */
+
+// ... or at the IPD, either.
+#ifdef NDEBUG
+# define _ARR_DBGINF_DECL
+# define _ARR_SET_DBGINF(descr, co, es) ((co), (es))
+#else
+# define _ARR_DBGINF_DECL int cookie; size_t eltsize;
+# define _ARR_SET_DBGINF(descr, co, es)                                        \
+    ((descr)->cookie = (co), (descr)->eltsize = (es))
+#endif
+
+#define ARR_STRUCT(type, _nelts)                                               \
+  struct {                                                                     \
+    _ARR_DBGINF_DECL                                                           \
+    union {                                                                    \
+      struct obstack *obstack; /* dynamic: allocated on this obstack */        \
+      int allocated;                   /* flexible: #slots allocated */        \
+    } u;                                                                       \
+    int nelts;                                                                 \
+    union {                                                                    \
+      type elts[(_nelts)];                                                     \
+      aligned_type align[1];                                                   \
+    } v;                                                                       \
+  }
+
+typedef ARR_STRUCT (aligned_type, 1) _arr_descr;
+
+extern _arr_descr arr_mt_descr;
+
+void *_new_arr_f (int, size_t);
+void _del_arr_f (void *);
+void *_new_arr_d (struct obstack *, int, size_t);
+void *_arr_resize (void *, int, size_t);
+void *_arr_setlen (void *, int, size_t);
+
+#define _ARR_ELTS_OFFS offsetof (_arr_descr, v.elts)
+#define _ARR_DESCR(elts) ((_arr_descr *)(void *)((char *)(elts) - _ARR_ELTS_OFFS))
+
+#endif
diff --git a/ir/adt/cookies.h b/ir/adt/cookies.h
new file mode 100644 (file)
index 0000000..5450b57
--- /dev/null
@@ -0,0 +1,24 @@
+/* Magic cookies for dynamic data structures
+   Copyright (C) 1995, 1996 Christian von Roques & Markus Armbruster
+   All rights reserved.  */
+
+#ifndef _COOKIES_H
+#define _COOKIES_H
+
+/* Arrays */
+#define ARR_D_MAGIC    0xD138A4
+#define ARR_A_MAGIC    0xA138A4
+#define ARR_F_MAGIC    0xF138A4
+
+/* Pointer Double Ended Queue */
+#define PDEQ_COOKIE1   0xC00B8A
+#define PDEQ_COOKIE2   0x8A771E
+
+/* Small Pointer DICTionary */
+#define SPDICT_COOKIE1 0xB0031E7
+#define SPDICT_COOKIE2 0xBA17B003
+
+/* Line N_o_mbers ToDo: Warum o? */
+#define LINO_COOKIE    0x71b83bd5
+
+#endif
diff --git a/ir/adt/host.h b/ir/adt/host.h
new file mode 100644 (file)
index 0000000..d3131fc
--- /dev/null
@@ -0,0 +1,46 @@
+/* Declarations describing the host machine and C compiler.
+   Copyright (C) 1995, 1996 Markus Armbruster
+   All rights reserved.*/
+
+#ifndef _HOST_H
+#define _HOST_H
+
+#include <stddef.h>
+
+
+/* A size handled efficiently by malloc(), at least 1K.  */
+#define PREF_MALLOC_SIZE 2048
+
+
+/* GNU C's __attribute__ */
+
+/* According to the documentation, the attributes we are interested in
+   work with 2.5, but we encountered trouble before 2.7.  */
+#if defined (__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
+# define HAVE_ATTRIBUTE 1
+# define ATTRIBUTE(attrs) __attribute__ (attrs)
+#else
+# define ATTRIBUTE(attrs)
+#endif
+
+
+/* Alignment */
+
+/* A type that has most constrained alignment.  */
+typedef union {
+  long double d;
+  void *p;
+  long l;
+} aligned_type ATTRIBUTE ((aligned));
+
+/* Inquiring about the alignment.  */
+#ifdef __GNUC__
+# define ALIGNOF(type) __alignof__ (type)
+#else
+# define ALIGNOF(type) offsetof (struct { char c; type d; }, d)
+#endif
+
+/* Maximal alignment required for any type.  */
+#define MAX_ALIGN ALIGNOF (aligned_type)
+
+#endif
diff --git a/ir/adt/obst.h b/ir/adt/obst.h
new file mode 100644 (file)
index 0000000..4701b43
--- /dev/null
@@ -0,0 +1,12 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# include <obstack.h>
+# include <malloc.h>
+
+# define obstack_chunk_alloc xmalloc
+# define obstack_chunk_free free
diff --git a/ir/adt/pdeq.c b/ir/adt/pdeq.c
new file mode 100644 (file)
index 0000000..9fab93a
--- /dev/null
@@ -0,0 +1,467 @@
+/* Pdeq --- double ended queue of generic pointers.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+# ifdef HAVE_STRING_H
+#  include <string.h>
+# endif
+#include "tune.h"
+#include "cookies.h"
+#include "debug.h"
+#include "malloc.h"
+#include "pdeq.h"
+
+/* # of data items in block */
+#define NDATA ((int)((PREF_MALLOC_SIZE - offsetof (pdeq, data)) / sizeof (void *)))
+
+#ifdef NDEBUG
+# define VRFY(dq) ((void)0)
+#else
+# define VRFY(dq) \
+    (d_(df_vrfy_level,1) ? _pdeq_vrfy ((dq)) : assert ((dq) && ((dq)->cookie == PDEQ_COOKIE1)))
+#endif
+
+
+struct pdeq {
+#ifndef NDEBUG
+  unsigned cookie;
+#endif
+  pdeq *l_end, *r_end;         /* left and right ends of the deque */
+  pdeq *l, *r;                 /*  left and right neighbour */
+  int n, p;
+  const void *data[1];
+};
+
+
+/* cache of unused, pdeq blocks to speed up new_pdeq and del_pdeq. */
+/* +1 for compilers that can't grok empty arrays */
+pdeq *pdeq_block_cache[TUNE_NSAVED_PDEQS+1];
+unsigned pdeqs_cached;         /* # pdeqs in pdeq_store */
+
+
+static inline void
+free_pdeq_block (pdeq *p)
+{
+#ifndef NDEBUG
+  p->cookie = 0xbadf00d1;
+#endif
+  if (pdeqs_cached < TUNE_NSAVED_PDEQS) {
+    if (d_ (df_pdeq, 2)) printf ("[%p ==> pdeq_block_cache] ", p);
+    pdeq_block_cache[pdeqs_cached++] = p;
+  } else {
+    if (d_ (df_pdeq, 2)) printf ("[%p ==> free] ", p);
+    xfree (p);
+  }
+}
+
+
+static inline pdeq *
+alloc_pdeq_block (void)
+{
+  pdeq *p;
+  if (TUNE_NSAVED_PDEQS && pdeqs_cached) {
+    p = pdeq_block_cache[--pdeqs_cached];
+    if (d_ (df_pdeq, 2)) printf ("[pdeq_block_cache ==> %p] ", p);
+  } else {
+    p = xmalloc (PREF_MALLOC_SIZE);
+    if (d_ (df_pdeq, 2)) printf ("[malloc ==> %p] ", p);
+  }
+  return p;
+}
+
+
+#ifndef NDEBUG
+void
+_pdeq_vrfy (pdeq *dq)
+{
+  pdeq *q;
+
+  if (d_ (df_pdeq, 5)) printf ("[pdeq_vrfy %p] ", dq);
+
+  assert (   dq
+         && (dq->cookie == PDEQ_COOKIE1)
+         && (dq->l_end && dq->r_end));
+  q = dq->l_end;
+  while (q) {
+    assert (   ((q == dq) || (q->cookie == PDEQ_COOKIE2))
+           && ((q == dq->l_end) ^ (q->l!=0))
+           && ((q == dq->r_end) ^ (q->r!=0))
+           && (!q->l || (q == q->l->r))
+           && ((q->n>=0) && (q->n<=NDATA))
+           && ((q == dq->l_end) || (q == dq->r_end) || (q->n == NDATA))
+           && ((q->p>=0) && (q->p<NDATA)));
+    q = q->r;
+  }
+}
+#endif
+
+
+pdeq *
+new_pdeq (void)
+{
+  pdeq *dq;
+
+  dq = alloc_pdeq_block();
+
+#ifndef NDEBUG
+  dq->cookie = PDEQ_COOKIE1;
+#endif
+  dq->l_end = dq->r_end = dq;
+  dq->l = dq->r = NULL;
+  dq->n = dq->p = 0;
+
+  VRFY (dq);
+  if (d_ (df_pdeq, 1)) printf ("(new_pdeq ==> %p)\n", dq);
+  return dq;
+}
+
+
+pdeq *
+new_pdeq1 (const void *x)
+{
+  return pdeq_putr (new_pdeq(), x);
+}
+
+
+void
+del_pdeq (pdeq *dq)
+{
+  pdeq *q, *qq;
+
+  VRFY (dq);
+
+  q = dq->l_end;               /* left end of chain */
+  /* pdeq trunk empty, but !pdeq_empty() ==> trunk not in chain */
+  if (dq->n == 0 && dq->l_end != dq ) {
+    free_pdeq_block (dq);
+  }
+
+  /* Free all blocks in the pdeq chain */
+  do {
+    qq = q->r;
+    free_pdeq_block (q);
+  } while ((q = qq));
+
+  if (d_ (df_pdeq, 1)) printf ("(del_pdeq %p)\n", dq);
+}
+
+
+bool
+pdeq_empty (pdeq *dq)
+{
+  VRFY (dq);
+  if (d_ (df_pdeq, 4)) printf ("(pdeq_empty %p ==> %d)\n", dq, dq->l_end->n == 0);
+  return dq->l_end->n == 0;
+}
+
+
+int
+pdeq_len (pdeq *dq)
+{
+  int n;
+  pdeq *q;
+
+  VRFY (dq);
+
+  n = 0;
+  q = dq->l_end;
+  do {
+    n += q->n;
+    q = q->r;
+  }  while (q);
+
+  if (d_ (df_pdeq, 4)) printf ("(pdeq_len %p ==> %d)\n", dq, n);
+  return n;
+}
+
+
+pdeq *
+pdeq_putr (pdeq *dq, const void *x)
+{
+  pdeq *rdq;
+  int n;
+  bool pr = 0;
+
+  VRFY (dq);
+
+  rdq = dq->r_end;
+  if (rdq->n >= NDATA) {       /* tailblock full */
+    pdeq *ndq;
+
+    ndq = dq;                  /* try to reuse trunk, but ... */
+    if (dq->n) {               /* ... if trunk used */
+      /* allocate and init new block */
+      ndq = alloc_pdeq_block ();
+      pr = d_ (df_pdeq, 2);
+#ifndef NDEBUG
+      ndq->cookie = PDEQ_COOKIE2;
+#endif
+      ndq->l_end = ndq->r_end = NULL;
+    }
+
+    ndq->r = NULL;
+    ndq->l = rdq; rdq->r = ndq;
+    ndq->n = 0; ndq->p = 0;
+    dq->r_end = ndq;
+    rdq = ndq;
+  }
+
+  n = rdq->n++ + rdq->p;
+  if (n >= NDATA) n -= NDATA;
+
+  rdq->data[n] = x;
+
+  VRFY (dq);
+  if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_putr %p %p)\n", dq, x);
+  return dq;
+}
+
+
+pdeq *
+pdeq_putl (pdeq *dq, const void *x)
+{
+  pdeq *ldq;
+  int p;
+  bool pr = 0;
+
+  VRFY (dq);
+
+  ldq = dq->l_end;
+  if (ldq->n >= NDATA) {       /* headblock full */
+    pdeq *ndq;
+
+    ndq = dq;                  /* try to reuse trunk, but ... */
+    if (dq->n) {               /* ... if trunk used */
+      /* allocate and init new block */
+      ndq = alloc_pdeq_block ();
+      pr = d_ (df_pdeq, 2);
+#ifndef NDEBUG
+      ndq->cookie = PDEQ_COOKIE2;
+#endif
+      ndq->l_end = ndq->r_end = NULL;
+    }
+
+    ndq->l = NULL;
+    ndq->r = ldq; ldq->l = ndq;
+    ndq->n = 0; ndq->p = 0;
+    dq->l_end = ndq;
+    ldq = ndq;
+  }
+
+  ldq->n++;
+  p = ldq->p - 1;
+  if (p < 0) p += NDATA;
+  ldq->p = p;
+
+  ldq->data[p] = x;
+
+  VRFY (dq);
+  if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_putl %p %p)\n", dq, x);
+  return dq;
+}
+
+
+void *
+pdeq_getr (pdeq *dq)
+{
+  pdeq *rdq;
+  const void *x;
+  int n;
+  bool pr = 0;
+
+  VRFY (dq);
+  assert (dq->l_end->n);
+
+  rdq = dq->r_end;
+  n = rdq->p + --rdq->n;
+  if (n>=NDATA) n -= NDATA;
+  x = rdq->data[n];
+
+  if (rdq->n == 0) {
+    if (rdq->l) {
+      dq->r_end = rdq->l;
+      rdq->l->r = NULL;
+      rdq->l = NULL;
+    } else {
+      dq->r_end = dq->l_end = dq;
+    }
+    if (dq != rdq) {
+      free_pdeq_block (rdq);
+      pr = d_ (df_pdeq, 2);
+    }
+  }
+
+  VRFY (dq);
+  if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_getr %p ==> %p)\n", dq, x);
+  return (void *)x;
+}
+
+
+void *
+pdeq_getl (pdeq *dq)
+{
+  pdeq *ldq;
+  const void *x;
+  int p;
+  bool pr = 0;
+
+  VRFY (dq);
+  assert (dq->l_end->n);
+
+  ldq = dq->l_end;
+  p = ldq->p;
+  x = ldq->data[p];
+  if (++p >= NDATA) p = 0;
+  ldq->p = p;
+
+  if (--ldq->n == 0) {
+    if (ldq->r) {
+      dq->l_end = ldq->r;
+      ldq->r->l = NULL;
+      ldq->r = NULL;
+    } else {
+      dq->l_end = dq->r_end = dq;
+    }
+    if (dq != ldq) {
+      free_pdeq_block (ldq);
+      pr = d_ (df_pdeq, 2);
+    }
+  }
+
+  VRFY (dq);
+  if (d_ (df_pdeq, 3) || pr) printf ("(pdeq_getl %p ==> %p)\n", dq, x);
+  return (void *)x;
+}
+
+
+bool
+pdeq_contains (pdeq *dq, const void *x)
+{
+  pdeq *q;
+
+  VRFY (dq);
+
+  q = dq->l_end;
+  do {
+    int p, ep;
+
+    p = q->p; ep = p + q->n;
+
+    if (ep > NDATA) {
+      do if (q->data[p] == x) goto found; while (++p < NDATA);
+      p = 0;
+      ep -= NDATA;
+    }
+
+    while (p < ep) if (q->data[p++] == x) goto found;
+
+    q = q->r;
+  } while (q);
+
+  if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p ==> 0)\n", dq, x);
+  return 0;
+
+found:  /* The two gotos can be optimized away, if !DEBUG */
+  if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p ==> 1)\n", dq, x);
+  return 1;
+}
+
+
+void *
+pdeq_search (pdeq *dq, cmp_fun cmp, const void *key)
+{
+  pdeq *q;
+  int p;
+
+  VRFY (dq);
+
+  q = dq->l_end;
+  do {
+    int ep;
+
+    p = q->p; ep = p + q->n;
+
+    if (ep > NDATA) {
+      do if (!cmp (q->data[p], key)) goto found; while (++p < NDATA);
+      p = 0;
+      ep -= NDATA;
+    }
+
+    while (p < ep) if (!cmp (q->data[p++], key)) goto found;
+
+    q = q->r;
+  } while (q);
+
+  if (d_ (df_pdeq, 3)) printf ("(pdeq_search %p %p %p ==> 0)\n", dq, cmp, key);
+  return NULL;
+
+found:  /* The two gotos can be optimized away, if !DEBUG */
+  if (d_ (df_pdeq, 3)) printf ("(pdeq_contains %p %p %p ==> %p)\n",
+                              dq, cmp, key, q->data[p]);
+  return (void *)q->data[p-1];
+}
+
+
+void **
+pdeq_copyl (pdeq *dq, const void **dst)
+{
+  pdeq *q;
+  const void **d = dst;
+
+  VRFY (dq);
+
+  q = dq->l_end;
+  while (q) {
+    int p, n;
+
+    p = q->p; n = q->n;
+
+    if (n + p > NDATA) {
+      int nn = NDATA - p;
+      memcpy (d, &q->data[p], nn * sizeof (void *)); d += nn;
+      p = 0; n -= nn;
+    }
+
+    memcpy (d, &q->data[p], n * sizeof (void *)); d += n;
+
+    q = q->r;
+  }
+
+  if (d_ (df_pdeq, 3)) printf ("(pdeq_copyl %p %p ==> %p)\n", dq, dst, d);
+  return (void **)dst;
+}
+
+
+void **
+pdeq_copyr (pdeq *dq, const void **dst)
+{
+  pdeq *q;
+  const void **d = dst;
+
+  VRFY (dq);
+
+  q = dq->r_end;
+  while (q) {
+    int p, i;
+
+    p = q->p; i = q->n + p - 1;
+    if (i >= NDATA) {
+      i -= NDATA;
+      do *d++ = q->data[i]; while (--i >= 0);
+      i = NDATA - 1;
+    }
+
+    do *d++ = q->data[i]; while (--i >= p);
+
+    q = q->l;
+  }
+
+  if (d_ (df_pdeq, 3)) printf ("(pdeq_copyr %p %p ==> %p)\n", dq, dst, d);
+  return (void **)dst;
+}
diff --git a/ir/adt/pdeq.h b/ir/adt/pdeq.h
new file mode 100644 (file)
index 0000000..a01dca3
--- /dev/null
@@ -0,0 +1,32 @@
+/* Declarations for pdeq.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+#ifndef _PDEQ_H
+#define _PDEQ_H
+
+#include "misc.h"
+
+typedef struct pdeq pdeq;
+
+pdeq *new_pdeq (void);
+pdeq *new_pdeq1 (const void *);
+void del_pdeq (pdeq *);
+int pdeq_len (pdeq *);
+bool pdeq_empty (pdeq *);
+bool pdeq_contains (pdeq *, const void *);
+void *pdeq_search (pdeq *, cmp_fun cmp, const void *key);
+void **pdeq_copyl (pdeq *, const void **);
+void **pdeq_copyr (pdeq *, const void **);
+pdeq *pdeq_putl (pdeq *, const void *);
+pdeq *pdeq_putr (pdeq *, const void *);
+void *pdeq_getl (pdeq *);
+void *pdeq_getr (pdeq *);
+
+#ifdef NDEBUG
+#define PDEQ_VRFY(deq) ((void)0)
+#else
+#define PDEQ_VRFY(deq) _pdeq_vrfy ((deq))
+void _pdeq_vrfy(pdeq *dq);
+#endif
+
+#endif
diff --git a/ir/adt/pset.h b/ir/adt/pset.h
new file mode 100644 (file)
index 0000000..d51f062
--- /dev/null
@@ -0,0 +1,70 @@
+/* Declarations for pset.
+   Copyright (C) 1995, 1996 Markus Armbruster */
+
+#ifndef _PSET_H
+#define _PSET_H
+
+#include <stddef.h>
+
+typedef struct pset pset;
+
+typedef struct {
+  unsigned hash;
+  void *dptr;
+} pset_entry;
+
+
+typedef int (*pset_cmp_fun) (const void *, const void *);
+
+pset *new_pset (pset_cmp_fun, int slots);
+void del_pset (pset *);
+
+void *pset_find (pset *, const void *key, unsigned hash);
+void *pset_insert (pset *, const void *key, unsigned hash);
+pset_entry *pset_hinsert (pset *, const void *key, unsigned hash);
+void *pset_remove (pset *, const void *key, unsigned hash);
+
+void *pset_first (pset *);
+void *pset_next (pset *);
+void pset_break (pset *);
+
+#define new_pset(cmp, slots) (PSET_TRACE (new_pset) ((cmp), (slots)))
+#define pset_find(pset, key, hash) \
+  _pset_search ((pset), (key), (hash), _pset_find)
+#define pset_insert(pset, key, hash) \
+  _pset_search ((pset), (key), (hash), _pset_insert)
+#define pset_hinsert(pset, key, hash) \
+  ((pset_entry *)_pset_search ((pset), (key), (hash), _pset_hinsert))
+
+#ifdef STATS
+void pset_stats (pset *);
+#else
+# define pset_stats(s) ((void)0)
+#endif
+
+#ifdef DEBUG
+void pset_describe (pset *);
+#endif
+
+/* @@@ NYI */
+#define PSET_VRFY(pset) (void)0
+
+
+/* Private */
+
+typedef enum { _pset_find, _pset_insert, _pset_hinsert } _pset_action;
+
+void *_pset_search (pset *, const void *, unsigned, _pset_action);
+
+#if defined(DEBUG) && defined(HAVE_GNU_MALLOC)
+extern const char *pset_tag;
+# ifdef PSET_ID
+#   define PSET_TRACE pset_tag = SET_ID,
+# else
+#   define PSET_TRACE pset_tag = __FILE__,
+# endif
+#else /* !(DEBUG && HAVE_GNU_MALLOC) */
+#   define PSET_TRACE
+#endif /* !(DEBUG && HAVE_GNU_MALLOC) */
+
+#endif
diff --git a/ir/adt/set.c b/ir/adt/set.c
new file mode 100644 (file)
index 0000000..9c44703
--- /dev/null
@@ -0,0 +1,496 @@
+/* Set --- collection of entries that are unique wrt to a key.
+   Copyright (C) 1995, 1996 Markus Armbruster */
+
+/*  This code is derived from:
+
+    From: ejp@ausmelb.oz.AU (Esmond Pitt)
+    Date: Tue, 7 Mar 1989 22:06:26 GMT
+    Subject: v06i042: dynamic hashing version of hsearch(3)
+    Message-ID: <1821@basser.oz>
+    Newsgroups: comp.sources.misc
+    Sender: msgs@basser.oz
+
+    Posting-number: Volume 6, Issue 42
+    Submitted-By: Esmond Pitt <ejp@ausmelb.oz.AU>
+    Archive-name: dynamic-hash
+
+    ** Dynamic hashing, after CACM April 1988 pp 446-457, by Per-Ake Larson.
+    ** Coded into C, with minor code improvements, and with hsearch(3) interface,
+    ** by ejp@ausmelb.oz, Jul 26, 1988: 13:16;
+
+    TODO: Fix Esmond's ugly MixedCapsIdentifiers ;->
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef PSET
+# define SET pset
+# define PMANGLE(pre) pre##_pset
+# define MANGLEP(post) pset_##post
+# define MANGLE(pre, post) pre##pset##post
+# define EQUAL(cmp, elt, key, siz) (!(cmp) ((elt)->entry.dptr, (key)))
+#else
+# define SET set
+# define PMANGLE(pre) pre##_set
+# define MANGLEP(post) set_##post
+# define MANGLE(pre, post) pre##set##post
+# define EQUAL(cmp, elt, key, siz) \
+    (((elt)->entry.size == (siz)) && !(cmp) ((elt)->entry.dptr, (key), (siz)))
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "misc.h"
+#ifdef PSET
+# include "pset.h"
+#else
+# include "set.h"
+#endif
+
+#define TOBSTACK_ID MANGLEP(tag)
+#include "obst.h"
+
+
+#define SEGMENT_SIZE_SHIFT     8
+#define SEGMENT_SIZE           (1 << SEGMENT_SIZE_SHIFT)
+#define DIRECTORY_SIZE_SHIFT   8
+#define DIRECTORY_SIZE         (1 << DIRECTORY_SIZE_SHIFT)
+#define MAX_LOAD_FACTOR        4
+
+
+typedef struct element {
+  struct element *chain;
+  MANGLEP (entry) entry;
+} Element, *Segment;
+
+
+struct SET {
+  short        p;                      /* Next bucket to be split      */
+  short        maxp;                   /* upper bound on p during expansion    */
+  int nkey;                    /* current # keys       */
+  short        nseg;                   /* current # segments   */
+  Segment *dir[DIRECTORY_SIZE];
+  MANGLEP(cmp_fun) cmp;                /* function comparing entries */
+  int iter_i, iter_j;
+  Element *iter_tail;          /* non-NULL while iterating over elts */
+#ifdef PSET
+  Element *free_list;
+#endif
+  struct obstack obst;
+#ifdef STATS
+  int naccess, ncollision, ndups;
+  int max_chain_len;
+#endif
+#ifdef DEBUG
+  const char *tag;
+#endif
+};
+
+
+#ifdef STATS
+
+void
+MANGLEP(stats) (SET *table)
+{
+  int nfree = 0;
+#ifdef PSET
+  Element *q = table->free_list;
+  while (q) { q = q->chain; ++nfree; }
+#endif
+  printf ("     accesses  collisions        keys  duplicates     longest      wasted\n%12d%12d%12d%12d%12d%12d\n",
+         table->naccess, table->ncollision, table->nkey, table->ndups, table->max_chain_len, nfree);
+}
+
+static inline void
+stat_chain_len (SET *table, int chain_len)
+{
+  table->ncollision += chain_len;
+  if (table->max_chain_len < chain_len) table->max_chain_len = chain_len;
+}
+
+# define stat_access(table) (++(table)->naccess)
+# define stat_dup(table) (++(table)->ndups)
+
+#else /* !STATS */
+
+# define stat_chain_len(table, chain_len) ((void)0)
+# define stat_access(table) ((void)0)
+# define stat_dup(table) ((void)0)
+
+#endif /* !STATS */
+
+#ifdef DEBUG
+
+const char *MANGLEP(tag);
+
+
+void
+MANGLEP(describe) (SET *table)
+{
+  int i, j, collide;
+  Element *ptr;
+  Segment *seg;
+
+  printf ("p=%d maxp=%d nkey=%d nseg=%d\n",
+         table->p, table->maxp, table->nkey, table->nseg);
+  for (i = 0;  i < table->nseg;  i++) {
+    seg = table->dir[i];
+    for (j = 0;  j < SEGMENT_SIZE;  j++) {
+      collide = 0;
+      ptr = seg[j];
+      while (ptr) {
+       if (collide) printf ("<%3d>", collide);
+       else printf ("table");
+       printf ("[%d][%3d]: %u %p\n", i, j, ptr->entry.hash, ptr->entry.dptr);
+       ptr = ptr->chain;
+       collide++;
+      }
+    }
+  }
+}
+
+#endif /* !DEBUG */
+
+
+SET *
+(PMANGLE(new)) (MANGLEP(cmp_fun) cmp, int nslots)
+{
+  int i;
+  SET *table = xmalloc (sizeof (SET));
+
+  /* Adjust nslots up to next power of 2, minimum SEGMENT_SIZE */
+  assert (nslots >= 0);
+  for (i = SEGMENT_SIZE;  i < nslots;  i <<= 1) assert (i < (i << 1));
+  nslots = i >> SEGMENT_SIZE_SHIFT;
+
+  table->nseg = table->p = table->nkey = 0;
+  table->maxp = nslots << SEGMENT_SIZE_SHIFT;
+  table->cmp = cmp;
+  table->iter_tail = NULL;
+#ifdef PSET
+  table->free_list = NULL;
+#endif
+  obstack_init (&table->obst);
+
+  /* Make segments */
+  for (i = 0;  i < nslots;  ++i) {
+    table->dir[i] = (Segment *)obstack_alloc (&table->obst,
+                                             sizeof (Segment) * SEGMENT_SIZE);
+
+    memset (table->dir[i], 0, sizeof (Segment) * SEGMENT_SIZE);
+    table->nseg++;
+  }
+
+#ifdef STATS
+  table->naccess = table->ncollision = table->ndups = 0;
+  table->max_chain_len = 0;
+#endif
+#ifdef DEBUG
+  table->tag = MANGLEP(tag);
+#endif
+  return table;
+}
+
+
+void
+PMANGLE(del) (SET *table)
+{
+#ifdef DEBUG
+  MANGLEP(tag) = table->tag;
+#endif
+  obstack_free (&table->obst, NULL);
+  xfree (table);
+}
+
+
+static inline int
+iter_step (SET *table)
+{
+  if (++table->iter_j >= SEGMENT_SIZE) {
+    table->iter_j = 0;
+    if (++table->iter_i >= table->nseg) {
+      table->iter_i = 0;
+      return 0;
+    }
+  }
+  return 1;
+}
+
+
+void *
+MANGLEP(first) (SET *table)
+{
+  assert (!table->iter_tail);
+  table->iter_i = 0;
+  table->iter_j = 0;
+  while (!table->dir[table->iter_i][table->iter_j]) {
+    if (!iter_step (table)) return NULL;
+  }
+  table->iter_tail = table->dir[table->iter_i][table->iter_j];
+  assert (table->iter_tail->entry.dptr);
+  return table->iter_tail->entry.dptr;
+}
+
+
+void *
+MANGLEP(next) (SET *table)
+{
+  assert (table->iter_tail);
+  table->iter_tail = table->iter_tail->chain;
+  if (!table->iter_tail) {
+    do {
+      if (!iter_step (table)) return NULL;
+    } while (!table->dir[table->iter_i][table->iter_j]);
+    table->iter_tail = table->dir[table->iter_i][table->iter_j];
+  }
+  assert (table->iter_tail->entry.dptr);
+  return table->iter_tail->entry.dptr;
+}
+
+void
+MANGLEP(break) (SET *table)
+{
+  assert (table->iter_tail);
+  table->iter_tail = NULL;
+}
+
+
+static inline unsigned
+Hash (SET *table, unsigned h)
+{
+  unsigned address;
+
+  address = h & (table->maxp - 1);
+  if (address < (unsigned)table->p)
+    address = h & ((table->maxp << 1) - 1); /* h % (2*table->maxp) */
+  return address;
+}
+
+
+static inline int
+loaded (SET *table)
+{
+  return (  ++table->nkey
+         > (table->nseg << SEGMENT_SIZE_SHIFT) * MAX_LOAD_FACTOR);
+}
+
+
+static void
+expand_table (SET *table)
+{
+  unsigned NewAddress;
+  int OldSegmentIndex, NewSegmentIndex;
+  int OldSegmentDir, NewSegmentDir;
+  Segment *OldSegment;
+  Segment *NewSegment;
+  Element *Current;
+  Element **Previous;
+  Element **LastOfNew;
+
+  if (table->maxp + table->p < (DIRECTORY_SIZE << SEGMENT_SIZE_SHIFT)) {
+    /* Locate the bucket to be split */
+    OldSegmentDir = table->p >> SEGMENT_SIZE_SHIFT;
+    OldSegment = table->dir[OldSegmentDir];
+    OldSegmentIndex = table->p & (SEGMENT_SIZE-1);
+
+    /* Expand address space; if necessary create a new segment */
+    NewAddress = table->maxp + table->p;
+    NewSegmentDir = NewAddress >> SEGMENT_SIZE_SHIFT;
+    NewSegmentIndex = NewAddress & (SEGMENT_SIZE-1);
+    if (NewSegmentIndex == 0) {
+      table->dir[NewSegmentDir] =
+       (Segment *)obstack_alloc (&table->obst,
+                                 sizeof(Segment) * SEGMENT_SIZE);
+    }
+    NewSegment = table->dir[NewSegmentDir];
+
+    /* Adjust state variables */
+    table->p++;
+    if (table->p == table->maxp) {
+      table->maxp <<= 1;       /* table->maxp *= 2     */
+      table->p = 0;
+    }
+    table->nseg++;
+
+    /* Relocate records to the new bucket */
+    Previous = &OldSegment[OldSegmentIndex];
+    Current = *Previous;
+    LastOfNew = &NewSegment[NewSegmentIndex];
+    *LastOfNew = NULL;
+    while (Current != NULL) {
+      if (Hash (table, Current->entry.hash) == NewAddress) {
+       /* move to new chain */
+       *LastOfNew = Current;
+       *Previous = Current->chain;
+       LastOfNew = &Current->chain;
+       Current = Current->chain;
+       *LastOfNew = NULL;
+      } else {
+       /* leave on old chain */
+       Previous = &Current->chain;
+       Current = Current->chain;
+      }
+    }
+  }
+}
+
+
+void *
+MANGLE(_,_search) (SET *table,
+                  const void *key,
+#ifndef PSET
+                  size_t size,
+#endif
+                  unsigned hash,
+                  MANGLE(_,_action) action)
+{
+  unsigned h;
+  Segment *CurrentSegment;
+  int SegmentIndex;
+  MANGLEP(cmp_fun) cmp = table->cmp;
+  Segment q;
+  int chain_len = 0;
+
+  assert (table);
+  assert (!table->iter_tail);
+  assert (key);
+#ifdef DEBUG
+  MANGLEP(tag) = table->tag;
+#endif
+  stat_access (table);
+
+  /* Find collision chain */
+  h = Hash (table, hash);
+  SegmentIndex = h & (SEGMENT_SIZE-1);
+  CurrentSegment = table->dir[h >> SEGMENT_SIZE_SHIFT];
+  assert (CurrentSegment != NULL);
+  q = CurrentSegment[SegmentIndex];
+
+  /* Follow collision chain */
+  while (q && !EQUAL (cmp, q, key, size)) {
+    q = q->chain;
+    ++chain_len;
+  }
+
+  stat_chain_len (table, chain_len);
+
+  if (!q && (action != MANGLE(_,_find))) { /* not found, insert */
+    if (CurrentSegment[SegmentIndex]) stat_dup (table);
+
+#ifdef PSET
+    if (table->free_list) {
+      q = table->free_list;
+      table->free_list = table->free_list->chain;
+    } else {
+      q = obstack_alloc (&table->obst, sizeof (Element));
+    }
+    q->entry.dptr = (void *)key;
+#else
+    obstack_blank (&table->obst, offsetof (Element, entry.dptr));
+    obstack_grow (&table->obst, key, size);
+    q = obstack_finish (&table->obst);
+    q->entry.size = size;
+#endif
+    q->chain = CurrentSegment[SegmentIndex];
+    q->entry.hash = hash;
+    CurrentSegment[SegmentIndex] = q;
+
+    if (loaded (table)) {
+      expand_table(table);     /* doesn't affect q */
+    }
+  }
+
+  if (!q) return NULL;
+  if (action == MANGLE(_,_hinsert)) return &q->entry;
+  return q->entry.dptr;
+}
+
+
+#ifdef PSET
+
+void *
+pset_remove (SET *table, const void *key, unsigned hash)
+{
+  unsigned h;
+  Segment *CurrentSegment;
+  int SegmentIndex;
+  pset_cmp_fun cmp = table->cmp;
+  Segment *p;
+  Segment q;
+  int chain_len = 0;
+
+  assert (table && !table->iter_tail);
+  stat_access (table);
+
+  /* Find collision chain */
+  h = Hash (table, hash);
+  SegmentIndex = h & (SEGMENT_SIZE-1);
+  CurrentSegment = table->dir[h >> SEGMENT_SIZE_SHIFT];
+  assert (CurrentSegment != NULL);
+  p = &CurrentSegment[SegmentIndex];
+
+  /* Follow collision chain */
+  while (!EQUAL (cmp, *p, key, size)) {
+    p = &(*p)->chain;
+    assert (*p);
+    ++chain_len;
+  }
+
+  stat_chain_len (table, chain_len);
+
+  q = *p;
+  *p = (*p)->chain;
+  q->chain = table->free_list;
+  table->free_list = q;
+
+  return q->entry.dptr;
+}
+
+
+void *
+(pset_find) (SET *se, const void *key, unsigned hash)
+{
+  return pset_find (se, key, hash);
+}
+
+
+void *
+(pset_insert) (SET *se, const void *key, unsigned hash)
+{
+  return pset_insert (se, key, hash);
+}
+
+
+MANGLEP(entry) *
+(pset_hinsert) (SET *se, const void *key, unsigned hash)
+{
+  return pset_hinsert (se, key, hash);
+}
+
+#else /* !PSET */
+
+void *
+(set_find) (set *se, const void *key, size_t size, unsigned hash)
+{
+  return set_find (se, key, size, hash);
+}
+
+
+void *
+(set_insert) (set *se, const void *key, size_t size, unsigned hash)
+{
+  return set_insert (se, key, size, hash);
+}
+
+
+set_entry *
+(set_hinsert) (set *se, const void *key, size_t size, unsigned hash)
+{
+  return set_hinsert (se, key, size, hash);
+}
+
+#endif /* !PSET */
diff --git a/ir/adt/set.h b/ir/adt/set.h
new file mode 100644 (file)
index 0000000..097742d
--- /dev/null
@@ -0,0 +1,70 @@
+/* Declarations for set.
+   Copyright (C) 1995, 1996 Markus Armbruster */
+
+#ifndef _SET_H
+#define _SET_H
+
+#include <stddef.h>
+
+typedef struct set set;
+
+typedef struct set_entry {
+  unsigned hash;
+  size_t size;
+  int dptr[1];                 /* data copied in must not need more
+                                  alignment than this */
+} set_entry;
+
+
+typedef int (*set_cmp_fun) (const void *elt, const void *key, size_t size);
+
+set *new_set (set_cmp_fun, int slots);
+void del_set (set *);
+
+void *set_find (set *, const void *key, size_t, unsigned hash);
+void *set_insert (set *, const void *key, size_t, unsigned hash);
+set_entry *set_hinsert (set *, const void *key, size_t, unsigned hash);
+
+void *set_first (set *);
+void *set_next (set *);
+void set_break (set *);
+
+#define new_set(cmp, slots) (SET_TRACE (new_set) ((cmp), (slots)))
+#define set_find(set, key, size, hash) \
+  _set_search ((set), (key), (size), (hash), _set_find)
+#define set_insert(set, key, size, hash) \
+  _set_search ((set), (key), (size), (hash), _set_insert)
+#define set_hinsert(set, key, size, hash) \
+  ((set_entry *)_set_search ((set), (key), (size), (hash), _set_hinsert))
+
+#define SET_VRFY(set) (void)0
+
+#ifdef STATS
+void set_stats (set *);
+#else
+# define set_stats(s) ((void)0)
+#endif
+
+#ifdef DEBUG
+void set_describe (set *);
+#endif
+
+
+/* Private */
+
+typedef enum { _set_find, _set_insert, _set_hinsert } _set_action;
+
+void *_set_search (set *, const void *, size_t, unsigned, _set_action);
+
+#if defined(DEBUG) && defined(HAVE_GNU_MALLOC)
+extern const char *set_tag;
+# ifdef SET_ID
+#   define SET_TRACE set_tag = SET_ID,
+# else
+#   define SET_TRACE set_tag = __FILE__,
+# endif
+#else /* !(DEBUG && HAVE_GNU_MALLOC) */
+#   define SET_TRACE
+#endif /* !(DEBUG && HAVE_GNU_MALLOC) */
+
+#endif
diff --git a/ir/adt/xmalloc.c b/ir/adt/xmalloc.c
new file mode 100644 (file)
index 0000000..1b121a0
--- /dev/null
@@ -0,0 +1,50 @@
+/* Xmalloc --- never failing wrappers for malloc() & friends.
+   Copyright (C) 1995, 1996 Markus Armbruster */
+
+/* @@@ ToDo: replace this file with the one from liberty.
+   [reimplement xstrdup, ... ] */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "misc.h"
+#include "panic.h"
+
+
+void *
+(xmalloc) (size_t size)
+{
+  void *res = malloc (size);
+
+  if (!res) xnomem ();
+  return res;
+}
+
+
+void *
+(xrealloc) (void *ptr, size_t size)
+{
+  /* ANSI blesses realloc (0, x) but SunOS chokes on it */
+  void *res = ptr ? realloc (ptr, size) : malloc (size);
+
+  if (!res) xnomem ();
+  return res;
+}
+
+
+char *
+(xstrdup) (const char *str)
+{
+  size_t len = strlen (str) + 1;
+  return memcpy ((xmalloc) (len), str, len);
+}
+
+
+void
+xnomem (void)
+{
+  panic ("out of memory");
+}
diff --git a/ir/common/Makefile b/ir/common/Makefile
new file mode 100644 (file)
index 0000000..4c45ee9
--- /dev/null
@@ -0,0 +1,66 @@
+# Hey, emacs, this is a -*- makefile -*-
+## Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Makefile for common
+
+
+CXX         = gcc
+CFLAGS      = -pipe -Wall # -ansi -pedantic
+CXXFLAGS    = # -g
+COPTFLAGS   = -O3
+LDFLAGS     =
+DEPENDFLAGS = -M
+LIBPATH     =
+LIBS        =
+X_LIBS      =
+INCLUDES    = -I../adt -I../common -I../debug -I../ident -I../include \
+             -I../ir -I../tr -I../tv
+X_INCLUDES  =
+
+SHELL       = /bin/sh
+MAKE        = /usr/bin/make
+
+MEMBERS         = common.m firm.m panic.m
+
+CFILES = $(MEMBERS:.m=.c)
+CFILES +=  xfprintf.c xfprintf.c xfprintf.c strerror.c
+
+HFILES = $(MEMBERS:.m=.h)
+HFILES +=  tune.h xp_help.h xprintf.h misc.h
+HFILES +=  common.h debug.h entity.h gmp.h host.h ident.h irgraph.h \
+          irmode.h irnode.h irop.h label.h misc.h obst.h pset.h set.h \
+           tv.h type.h xprintf.h xp_help.h
+
+OFILES = $(MEMBERS:%.m=../objects/%.o)
+OFILES +=  ../objects/xfprintf.o \
+          ../objects/xgprintf.o \
+          ../objects/xoprintf.o \
+          ../objects/strerror.o
+
+DFILES = $(MEMBERS:.m=.d)
+
+TARGET = all
+
+.PHONY: default all clean realclean install depend
+.SUFFIXES: .d .h .c .o
+.DEFAULT: $(TARGET)
+.SILENT: $(DFILES) clean  # hides output
+
+$(TARGET): $(DFILES) $(OFILES)
+
+%.d:    %.c
+       $(SHELL) -ec '$(CXX) $(DEPENDFLAGS) $(INCLUDES) $(X_INCLUDES) $< | sed '\''s/\($*\)\.o[ :]*/\.\.\/objects\/\1.o $@ : /g'\'' > $@'
+
+
+../objects/%.o:    %.c
+       $(CXX) $(CFLAGS) $(CXXFLAGS) $(COPTFLAGS) $(INCLUDES) $(X_INCLUDES) -c $< -o $@
+
+clean:
+       rm -f $(OFILES) $(DFILES)
+
+realclean:     clean
+       rm -f $(TARGET) *.flc TAGS
+
+-include $(DFILES)
diff --git a/ir/common/common.c b/ir/common/common.c
new file mode 100644 (file)
index 0000000..84e9d9a
--- /dev/null
@@ -0,0 +1,17 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer &
+**          Goetz Lindenmaier
+**
+** common.c:
+*/
+
+#include "common.h"
+#include "irgraph.h"
+
+/* returns the kind of the thing */
+firm_kind
+get_kind (void *firm_thing) {
+  return *(firm_kind *)firm_thing;
+}
diff --git a/ir/common/common.h b/ir/common/common.h
new file mode 100644 (file)
index 0000000..40fed98
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer &
+**          Goetz Lindenmaier
+**
+** common.h: common firm declarations
+*/
+
+# ifndef _COMMON_H_
+# define _COMMON_H_
+
+
+/* set to compile with extensions for compiler constructon lab. */
+# define UEBPRAKT 1
+
+/* If this flag is set, new_r_Phi_in uses an explicit stack for
+   allocating and deallocating Phi nodes.  Else it uses the obstack
+   as a stack! */
+#define USE_EXPICIT_PHI_IN_STACK 1
+
+/* a list of firm kinds */
+typedef enum {
+  k_entity,
+  k_type_class,
+  k_type_strct,
+  k_type_method,
+  k_type_union,
+  k_type_array,
+  k_type_enumeration,
+  k_type_pointer,
+  k_type_primitive,
+  k_ir_node
+} firm_kind;
+
+/* returns the kind of the thing */
+firm_kind get_kind(void *firm_thing);
+
+
+# endif /*_COMMON_H_ */
diff --git a/ir/common/firm.c b/ir/common/firm.c
new file mode 100644 (file)
index 0000000..18e3e3b
--- /dev/null
@@ -0,0 +1,27 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# include <stdio.h>
+# include "ident.h"
+# include "firm.h"
+# include "mangle.h"
+# include "xp_help.h"
+
+void
+init_firm (void)
+{
+  xprintf_register ('I', ident_print);
+  xprintf_register ('v', tarval_print);
+  xprintf_register ('R', ir_node_print);
+  id_init ();
+  tarval_init_1 ();
+  init_mode ();
+  tarval_init_2 ();
+  init_mangle ();
+  init_op ();
+  init_cons ();
+}
diff --git a/ir/common/firm.h b/ir/common/firm.h
new file mode 100644 (file)
index 0000000..088d4c7
--- /dev/null
@@ -0,0 +1,23 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** firm.h:
+*/
+
+# ifndef _FIRM_H_
+# define _FIRM_H_
+
+
+# include "entity.h"
+# include "ircons.h"
+# include "type.h"
+# include "iropt.h"
+# include "xprintf.h"
+
+
+/* initialize firm */
+void init_firm (void);
+
+# endif /* _FIRM_H_ */
diff --git a/ir/common/misc.h b/ir/common/misc.h
new file mode 100644 (file)
index 0000000..67fce7d
--- /dev/null
@@ -0,0 +1,83 @@
+/* Misc. declarations.
+   Copyright (C) 1995, 1996 Markus Armbruster
+   All rights reserved. */
+
+#ifndef _MISC_H
+#define _MISC_H
+
+
+/* Declare alloca() */
+
+#ifdef __GNUC__
+  /* @@@ on a true GNU system, this is defined by stdlib.h */
+# undef alloca
+# define alloca(size) __builtin_alloca (size)
+#else
+# if HAVE_ALLOCA_H
+#   include <alloca.h>
+# else
+#   if defined(_AIX) && !defined(C_ALLOCA)
+      /* if your version of AIX chokes on this, use gcc @@@ or alloca.o */
+#pragma alloca
+#   else
+#     ifndef alloca /* predefined by HP cc +Olibcalls */
+void *alloca ();
+#     endif
+#   endif
+# endif
+#endif
+
+
+#include "host.h"
+
+
+/* Alignment of nodes, cf common/tag.h, a power of two.
+
+   Most nodes are allocated from obstacks and therefore are aligned
+   identically on the obstacks' alignment boundary.  We'd like gcc to
+   align *all* nodes identically to avoid its cast-align warning and
+   perhaps allow for better code.  Since the common node alignment is
+   not known in time, we use an educated guess and check it against
+   the correct value later.  */
+#define NODE_ALIGN ALIGNOF (struct { void *p; int i; })
+
+
+/* Miscellaneous */
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+# define MIN(a,b) ((a) > (b) ? (b) : (a))
+#endif
+
+#define IS_POW2(n) ((((n)-1) & (n)) == 0)
+
+typedef unsigned char bool;
+typedef int (*cmp_fun) (const void *, const void *);
+
+
+/* xmalloc() & friends.
+
+   The macros set tmalloc_tag to __FILE__, the functions leave it
+   alone.  Use the latter if you set it yourself.  See tmalloc.c for
+   details.  */
+
+extern void *xmalloc (size_t);
+extern void *xrealloc (void *, size_t);
+extern char *xstrdup (const char *);
+extern void xnomem (void);
+
+# define xmalloc(size) (XMALLOC_TRACE (xmalloc) ((size)))
+# define xrealloc(ptr, size) (XMALLOC_TRACE (xrealloc) ((ptr), (size)))
+# define xstrdup(str) (XMALLOC_TRACE (xstrdup) ((str)))
+# define xfree(ptr) (XMALLOC_TRACE free ((ptr)))
+
+#if defined(HAVE_GNU_MALLOC) && defined(DEBUG)
+extern const char *tmalloc_tag;
+# define XMALLOC_TRACE tmalloc_tag = __FILE__,
+#else
+# define XMALLOC_TRACE
+#endif
+
+#endif
diff --git a/ir/common/panic.c b/ir/common/panic.c
new file mode 100644 (file)
index 0000000..d78757c
--- /dev/null
@@ -0,0 +1,22 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# include "panic.h"
+# include "xprintf.h"
+
+void
+panic (const char *fmt, ...)
+{
+  va_list ap;
+
+  fputs ("(panic) ", stderr);
+  va_start (ap, fmt);
+  xvfprintf (stderr, fmt, ap);
+  va_end (ap);
+  putc ('\n', stderr);
+  exit (1);
+}
diff --git a/ir/common/panic.h b/ir/common/panic.h
new file mode 100644 (file)
index 0000000..c403a85
--- /dev/null
@@ -0,0 +1,13 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# ifndef _PANIC_H_
+# define _PANIC_H_
+
+void panic (const char *fmt, ...);
+
+# endif /*_PANIC_H_ */
diff --git a/ir/common/strerror.c b/ir/common/strerror.c
new file mode 100644 (file)
index 0000000..6e24c7a
--- /dev/null
@@ -0,0 +1,831 @@
+/* Extended support for using errno values.
+   Written by Fred Fish.  fnf@cygnus.com
+   This file is in the public domain.  --Per Bothner.  */
+
+/* Slightly edited for Fiasco by Markus Armbruster */
+
+/* Fiasco's requirements: */
+#undef NEED_sys_errlist
+#define NEED_strerror
+
+
+#ifndef NEED_sys_errlist
+/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
+   might declare sys_errlist in a way that the compiler might consider
+   incompatible with our later declaration, perhaps by using const
+   attributes.  So we hide the declaration in errno.h (if any) using a
+   macro. */
+#define sys_errlist sys_errlist__
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef NEED_sys_errlist
+#undef sys_errlist
+#endif
+
+/*  Routines imported from standard C runtime libraries. */
+
+#ifdef __STDC__
+#include <stddef.h>
+extern void *malloc (size_t size);                             /* 4.10.3.3 */
+extern void *memset (void *s, int c, size_t n);                        /* 4.11.6.1 */
+#else  /* !__STDC__ */
+extern char *malloc ();                /* Standard memory allocater */
+extern char *memset ();
+#endif /* __STDC__ */
+
+#ifndef MAX
+#  define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/* Translation table for errno values.  See intro(2) in most UNIX systems
+   Programmers Reference Manuals.
+
+   Note that this table is generally only accessed when it is used at runtime
+   to initialize errno name and message tables that are indexed by errno
+   value.
+
+   Not all of these errnos will exist on all systems.  This table is the only
+   thing that should have to be updated as new error numbers are introduced.
+   It's sort of ugly, but at least its portable. */
+
+struct error_info
+{
+  int value;           /* The numeric value from <errno.h> */
+  const char *name;    /* The equivalent symbolic value */
+#ifdef NEED_sys_errlist
+  const char *msg;     /* Short message about this value */
+#endif
+};
+
+#ifdef NEED_sys_errlist
+#   define ENTRY(value, name, msg)     {value, name, msg}
+#else
+#   define ENTRY(value, name, msg)     {value, name}
+#endif
+
+static const struct error_info error_table[] =
+{
+#if defined (EPERM)
+  ENTRY(EPERM, "EPERM", "Not owner"),
+#endif
+#if defined (ENOENT)
+  ENTRY(ENOENT, "ENOENT", "No such file or directory"),
+#endif
+#if defined (ESRCH)
+  ENTRY(ESRCH, "ESRCH", "No such process"),
+#endif
+#if defined (EINTR)
+  ENTRY(EINTR, "EINTR", "Interrupted system call"),
+#endif
+#if defined (EIO)
+  ENTRY(EIO, "EIO", "I/O error"),
+#endif
+#if defined (ENXIO)
+  ENTRY(ENXIO, "ENXIO", "No such device or address"),
+#endif
+#if defined (E2BIG)
+  ENTRY(E2BIG, "E2BIG", "Arg list too long"),
+#endif
+#if defined (ENOEXEC)
+  ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"),
+#endif
+#if defined (EBADF)
+  ENTRY(EBADF, "EBADF", "Bad file number"),
+#endif
+#if defined (ECHILD)
+  ENTRY(ECHILD, "ECHILD", "No child processes"),
+#endif
+#if defined (EWOULDBLOCK)      /* Put before EAGAIN, sometimes aliased */
+  ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"),
+#endif
+#if defined (EAGAIN)
+  ENTRY(EAGAIN, "EAGAIN", "No more processes"),
+#endif
+#if defined (ENOMEM)
+  ENTRY(ENOMEM, "ENOMEM", "Not enough space"),
+#endif
+#if defined (EACCES)
+  ENTRY(EACCES, "EACCES", "Permission denied"),
+#endif
+#if defined (EFAULT)
+  ENTRY(EFAULT, "EFAULT", "Bad address"),
+#endif
+#if defined (ENOTBLK)
+  ENTRY(ENOTBLK, "ENOTBLK", "Block device required"),
+#endif
+#if defined (EBUSY)
+  ENTRY(EBUSY, "EBUSY", "Device busy"),
+#endif
+#if defined (EEXIST)
+  ENTRY(EEXIST, "EEXIST", "File exists"),
+#endif
+#if defined (EXDEV)
+  ENTRY(EXDEV, "EXDEV", "Cross-device link"),
+#endif
+#if defined (ENODEV)
+  ENTRY(ENODEV, "ENODEV", "No such device"),
+#endif
+#if defined (ENOTDIR)
+  ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"),
+#endif
+#if defined (EISDIR)
+  ENTRY(EISDIR, "EISDIR", "Is a directory"),
+#endif
+#if defined (EINVAL)
+  ENTRY(EINVAL, "EINVAL", "Invalid argument"),
+#endif
+#if defined (ENFILE)
+  ENTRY(ENFILE, "ENFILE", "File table overflow"),
+#endif
+#if defined (EMFILE)
+  ENTRY(EMFILE, "EMFILE", "Too many open files"),
+#endif
+#if defined (ENOTTY)
+  ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"),
+#endif
+#if defined (ETXTBSY)
+  ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"),
+#endif
+#if defined (EFBIG)
+  ENTRY(EFBIG, "EFBIG", "File too large"),
+#endif
+#if defined (ENOSPC)
+  ENTRY(ENOSPC, "ENOSPC", "No space left on device"),
+#endif
+#if defined (ESPIPE)
+  ENTRY(ESPIPE, "ESPIPE", "Illegal seek"),
+#endif
+#if defined (EROFS)
+  ENTRY(EROFS, "EROFS", "Read-only file system"),
+#endif
+#if defined (EMLINK)
+  ENTRY(EMLINK, "EMLINK", "Too many links"),
+#endif
+#if defined (EPIPE)
+  ENTRY(EPIPE, "EPIPE", "Broken pipe"),
+#endif
+#if defined (EDOM)
+  ENTRY(EDOM, "EDOM", "Math argument out of domain of func"),
+#endif
+#if defined (ERANGE)
+  ENTRY(ERANGE, "ERANGE", "Math result not representable"),
+#endif
+#if defined (ENOMSG)
+  ENTRY(ENOMSG, "ENOMSG", "No message of desired type"),
+#endif
+#if defined (EIDRM)
+  ENTRY(EIDRM, "EIDRM", "Identifier removed"),
+#endif
+#if defined (ECHRNG)
+  ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"),
+#endif
+#if defined (EL2NSYNC)
+  ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"),
+#endif
+#if defined (EL3HLT)
+  ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"),
+#endif
+#if defined (EL3RST)
+  ENTRY(EL3RST, "EL3RST", "Level 3 reset"),
+#endif
+#if defined (ELNRNG)
+  ENTRY(ELNRNG, "ELNRNG", "Link number out of range"),
+#endif
+#if defined (EUNATCH)
+  ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"),
+#endif
+#if defined (ENOCSI)
+  ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"),
+#endif
+#if defined (EL2HLT)
+  ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"),
+#endif
+#if defined (EDEADLK)
+  ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"),
+#endif
+#if defined (ENOLCK)
+  ENTRY(ENOLCK, "ENOLCK", "No record locks available"),
+#endif
+#if defined (EBADE)
+  ENTRY(EBADE, "EBADE", "Invalid exchange"),
+#endif
+#if defined (EBADR)
+  ENTRY(EBADR, "EBADR", "Invalid request descriptor"),
+#endif
+#if defined (EXFULL)
+  ENTRY(EXFULL, "EXFULL", "Exchange full"),
+#endif
+#if defined (ENOANO)
+  ENTRY(ENOANO, "ENOANO", "No anode"),
+#endif
+#if defined (EBADRQC)
+  ENTRY(EBADRQC, "EBADRQC", "Invalid request code"),
+#endif
+#if defined (EBADSLT)
+  ENTRY(EBADSLT, "EBADSLT", "Invalid slot"),
+#endif
+#if defined (EDEADLOCK)
+  ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"),
+#endif
+#if defined (EBFONT)
+  ENTRY(EBFONT, "EBFONT", "Bad font file format"),
+#endif
+#if defined (ENOSTR)
+  ENTRY(ENOSTR, "ENOSTR", "Device not a stream"),
+#endif
+#if defined (ENODATA)
+  ENTRY(ENODATA, "ENODATA", "No data available"),
+#endif
+#if defined (ETIME)
+  ENTRY(ETIME, "ETIME", "Timer expired"),
+#endif
+#if defined (ENOSR)
+  ENTRY(ENOSR, "ENOSR", "Out of streams resources"),
+#endif
+#if defined (ENONET)
+  ENTRY(ENONET, "ENONET", "Machine is not on the network"),
+#endif
+#if defined (ENOPKG)
+  ENTRY(ENOPKG, "ENOPKG", "Package not installed"),
+#endif
+#if defined (EREMOTE)
+  ENTRY(EREMOTE, "EREMOTE", "Object is remote"),
+#endif
+#if defined (ENOLINK)
+  ENTRY(ENOLINK, "ENOLINK", "Link has been severed"),
+#endif
+#if defined (EADV)
+  ENTRY(EADV, "EADV", "Advertise error"),
+#endif
+#if defined (ESRMNT)
+  ENTRY(ESRMNT, "ESRMNT", "Srmount error"),
+#endif
+#if defined (ECOMM)
+  ENTRY(ECOMM, "ECOMM", "Communication error on send"),
+#endif
+#if defined (EPROTO)
+  ENTRY(EPROTO, "EPROTO", "Protocol error"),
+#endif
+#if defined (EMULTIHOP)
+  ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"),
+#endif
+#if defined (EDOTDOT)
+  ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"),
+#endif
+#if defined (EBADMSG)
+  ENTRY(EBADMSG, "EBADMSG", "Not a data message"),
+#endif
+#if defined (ENAMETOOLONG)
+  ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"),
+#endif
+#if defined (EOVERFLOW)
+  ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"),
+#endif
+#if defined (ENOTUNIQ)
+  ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"),
+#endif
+#if defined (EBADFD)
+  ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"),
+#endif
+#if defined (EREMCHG)
+  ENTRY(EREMCHG, "EREMCHG", "Remote address changed"),
+#endif
+#if defined (ELIBACC)
+  ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"),
+#endif
+#if defined (ELIBBAD)
+  ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"),
+#endif
+#if defined (ELIBSCN)
+  ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"),
+#endif
+#if defined (ELIBMAX)
+  ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"),
+#endif
+#if defined (ELIBEXEC)
+  ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"),
+#endif
+#if defined (EILSEQ)
+  ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"),
+#endif
+#if defined (ENOSYS)
+  ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"),
+#endif
+#if defined (ELOOP)
+  ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"),
+#endif
+#if defined (ERESTART)
+  ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"),
+#endif
+#if defined (ESTRPIPE)
+  ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"),
+#endif
+#if defined (ENOTEMPTY)
+  ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"),
+#endif
+#if defined (EUSERS)
+  ENTRY(EUSERS, "EUSERS", "Too many users"),
+#endif
+#if defined (ENOTSOCK)
+  ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"),
+#endif
+#if defined (EDESTADDRREQ)
+  ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"),
+#endif
+#if defined (EMSGSIZE)
+  ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"),
+#endif
+#if defined (EPROTOTYPE)
+  ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"),
+#endif
+#if defined (ENOPROTOOPT)
+  ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"),
+#endif
+#if defined (EPROTONOSUPPORT)
+  ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"),
+#endif
+#if defined (ESOCKTNOSUPPORT)
+  ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"),
+#endif
+#if defined (EOPNOTSUPP)
+  ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
+#endif
+#if defined (EPFNOSUPPORT)
+  ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"),
+#endif
+#if defined (EAFNOSUPPORT)
+  ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"),
+#endif
+#if defined (EADDRINUSE)
+  ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"),
+#endif
+#if defined (EADDRNOTAVAIL)
+  ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"),
+#endif
+#if defined (ENETDOWN)
+  ENTRY(ENETDOWN, "ENETDOWN", "Network is down"),
+#endif
+#if defined (ENETUNREACH)
+  ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"),
+#endif
+#if defined (ENETRESET)
+  ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"),
+#endif
+#if defined (ECONNABORTED)
+  ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"),
+#endif
+#if defined (ECONNRESET)
+  ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"),
+#endif
+#if defined (ENOBUFS)
+  ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"),
+#endif
+#if defined (EISCONN)
+  ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"),
+#endif
+#if defined (ENOTCONN)
+  ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"),
+#endif
+#if defined (ESHUTDOWN)
+  ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
+#endif
+#if defined (ETOOMANYREFS)
+  ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"),
+#endif
+#if defined (ETIMEDOUT)
+  ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"),
+#endif
+#if defined (ECONNREFUSED)
+  ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"),
+#endif
+#if defined (EHOSTDOWN)
+  ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"),
+#endif
+#if defined (EHOSTUNREACH)
+  ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"),
+#endif
+#if defined (EALREADY)
+  ENTRY(EALREADY, "EALREADY", "Operation already in progress"),
+#endif
+#if defined (EINPROGRESS)
+  ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"),
+#endif
+#if defined (ESTALE)
+  ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"),
+#endif
+#if defined (EUCLEAN)
+  ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"),
+#endif
+#if defined (ENOTNAM)
+  ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"),
+#endif
+#if defined (ENAVAIL)
+  ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"),
+#endif
+#if defined (EISNAM)
+  ENTRY(EISNAM, "EISNAM", "Is a named type file"),
+#endif
+#if defined (EREMOTEIO)
+  ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"),
+#endif
+  ENTRY(0, NULL, NULL)
+};
+
+#ifdef EVMSERR
+/* This is not in the table, because the numeric value of EVMSERR (32767)
+   lies outside the range of sys_errlist[].  */
+static struct { int value; const char *name, *msg; }
+  evmserr = { EVMSERR, "EVMSERR", "VMS-specific error" };
+#endif
+
+/* Translation table allocated and initialized at runtime.  Indexed by the
+   errno value to find the equivalent symbolic value. */
+
+static const char **error_names;
+static int num_error_names = 0;
+
+/* Translation table allocated and initialized at runtime, if it does not
+   already exist in the host environment.  Indexed by the errno value to find
+   the descriptive string.
+
+   We don't export it for use in other modules because even though it has the
+   same name, it differs from other implementations in that it is dynamically
+   initialized rather than statically initialized. */
+
+#ifdef NEED_sys_errlist
+
+static int sys_nerr;
+static const char **sys_errlist;
+
+#else
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+#endif
+
+
+/*
+
+NAME
+
+       init_error_tables -- initialize the name and message tables
+
+SYNOPSIS
+
+       static void init_error_tables ();
+
+DESCRIPTION
+
+       Using the error_table, which is initialized at compile time, generate
+       the error_names and the sys_errlist (if needed) tables, which are
+       indexed at runtime by a specific errno value.
+
+BUGS
+
+       The initialization of the tables may fail under low memory conditions,
+       in which case we don't do anything particularly useful, but we don't
+       bomb either.  Who knows, it might succeed at a later point if we free
+       some memory in the meantime.  In any case, the other routines know
+       how to deal with lack of a table after trying to initialize it.  This
+       may or may not be considered to be a bug, that we don't specifically
+       warn about this particular failure mode.
+
+*/
+
+static void
+init_error_tables ()
+{
+  const struct error_info *eip;
+  int nbytes;
+
+  /* If we haven't already scanned the error_table once to find the maximum
+     errno value, then go find it now. */
+
+  if (num_error_names == 0)
+    {
+      for (eip = error_table; eip -> name != NULL; eip++)
+       {
+         if (eip -> value >= num_error_names)
+           {
+             num_error_names = eip -> value + 1;
+           }
+       }
+    }
+
+  /* Now attempt to allocate the error_names table, zero it out, and then
+     initialize it from the statically initialized error_table. */
+
+  if (error_names == NULL)
+    {
+      nbytes = num_error_names * sizeof (char *);
+      if ((error_names = (const char **) malloc (nbytes)) != NULL)
+       {
+         memset (error_names, 0, nbytes);
+         for (eip = error_table; eip -> name != NULL; eip++)
+           {
+             error_names[eip -> value] = eip -> name;
+           }
+       }
+    }
+
+#ifdef NEED_sys_errlist
+
+  /* Now attempt to allocate the sys_errlist table, zero it out, and then
+     initialize it from the statically initialized error_table. */
+
+  if (sys_errlist == NULL)
+    {
+      nbytes = num_error_names * sizeof (char *);
+      if ((sys_errlist = (const char **) malloc (nbytes)) != NULL)
+       {
+         memset (sys_errlist, 0, nbytes);
+         sys_nerr = num_error_names;
+         for (eip = error_table; eip -> name != NULL; eip++)
+           {
+             sys_errlist[eip -> value] = eip -> msg;
+           }
+       }
+    }
+
+#endif
+
+}
+
+/*
+
+NAME
+
+       errno_max -- return the max errno value
+
+SYNOPSIS
+
+       int errno_max ();
+
+DESCRIPTION
+
+       Returns the maximum errno value for which a corresponding symbolic
+       name or message is available.  Note that in the case where
+       we use the sys_errlist supplied by the system, it is possible for
+       there to be more symbolic names than messages, or vice versa.
+       In fact, the manual page for perror(3C) explicitly warns that one
+       should check the size of the table (sys_nerr) before indexing it,
+       since new error codes may be added to the system before they are
+       added to the table.  Thus sys_nerr might be smaller than value
+       implied by the largest errno value defined in <errno.h>.
+
+       We return the maximum value that can be used to obtain a meaningful
+       symbolic name or message.
+
+*/
+
+int
+errno_max ()
+{
+  int maxsize;
+
+  if (error_names == NULL)
+    {
+      init_error_tables ();
+    }
+  maxsize = MAX (sys_nerr, num_error_names);
+  return (maxsize - 1);
+}
+
+#ifdef NEED_strerror
+
+/*
+
+NAME
+
+       strerror -- map an error number to an error message string
+
+SYNOPSIS
+
+       char *strerror (int errnoval)
+
+DESCRIPTION
+
+       Maps an errno number to an error message string, the contents of
+       which are implementation defined.  On systems which have the external
+       variables sys_nerr and sys_errlist, these strings will be the same
+       as the ones used by perror().
+
+       If the supplied error number is within the valid range of indices
+       for the sys_errlist, but no message is available for the particular
+       error number, then returns the string "Error NUM", where NUM is the
+       error number.
+
+       If the supplied error number is not a valid index into sys_errlist,
+       returns NULL.
+
+       The returned string is only guaranteed to be valid only until the
+       next call to strerror.
+
+*/
+
+char *
+strerror (errnoval)
+  int errnoval;
+{
+  char *msg;
+  static char buf[32];
+
+#ifdef NEED_sys_errlist
+
+  if (error_names == NULL)
+    {
+      init_error_tables ();
+    }
+
+#endif
+
+  if ((errnoval < 0) || (errnoval >= sys_nerr))
+    {
+#ifdef EVMSERR
+      if (errnoval == evmserr.value)
+       msg = evmserr.msg;
+      else
+#endif
+      /* Out of range, just return NULL */
+      msg = NULL;
+    }
+  else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
+    {
+      /* In range, but no sys_errlist or no entry at this index. */
+      sprintf (buf, "Error %d", errnoval);
+      msg = buf;
+    }
+  else
+    {
+      /* In range, and a valid message.  Just return the message. */
+      msg = (char *) sys_errlist[errnoval];
+    }
+
+  return (msg);
+}
+
+#endif /* NEED_strerror */
+
+
+/*
+
+NAME
+
+       strerrno -- map an error number to a symbolic name string
+
+SYNOPSIS
+
+       const char *strerrno (int errnoval)
+
+DESCRIPTION
+
+       Given an error number returned from a system call (typically
+       returned in errno), returns a pointer to a string containing the
+       symbolic name of that error number, as found in <errno.h>.
+
+       If the supplied error number is within the valid range of indices
+       for symbolic names, but no name is available for the particular
+       error number, then returns the string "Error NUM", where NUM is
+       the error number.
+
+       If the supplied error number is not within the range of valid
+       indices, then returns NULL.
+
+BUGS
+
+       The contents of the location pointed to are only guaranteed to be
+       valid until the next call to strerrno.
+
+*/
+
+const char *
+strerrno (errnoval)
+  int errnoval;
+{
+  const char *name;
+  static char buf[32];
+
+  if (error_names == NULL)
+    {
+      init_error_tables ();
+    }
+
+  if ((errnoval < 0) || (errnoval >= num_error_names))
+    {
+#ifdef EVMSERR
+      if (errnoval == evmserr.value)
+       name = evmserr.name;
+      else
+#endif
+      /* Out of range, just return NULL */
+      name = NULL;
+    }
+  else if ((error_names == NULL) || (error_names[errnoval] == NULL))
+    {
+      /* In range, but no error_names or no entry at this index. */
+      sprintf (buf, "Error %d", errnoval);
+      name = (const char *) buf;
+    }
+  else
+    {
+      /* In range, and a valid name.  Just return the name. */
+      name = error_names[errnoval];
+    }
+
+  return (name);
+}
+
+/*
+
+NAME
+
+       strtoerrno -- map a symbolic errno name to a numeric value
+
+SYNOPSIS
+
+       int strtoerrno (char *name)
+
+DESCRIPTION
+
+       Given the symbolic name of a error number, map it to an errno value.
+       If no translation is found, returns 0.
+
+*/
+
+int
+strtoerrno (name)
+     const char *name;
+{
+  int errnoval = 0;
+
+  if (name != NULL)
+    {
+      if (error_names == NULL)
+       {
+         init_error_tables ();
+       }
+      for (errnoval = 0; errnoval < num_error_names; errnoval++)
+       {
+         if ((error_names[errnoval] != NULL) &&
+             (strcmp (name, error_names[errnoval]) == 0))
+           {
+             break;
+           }
+       }
+      if (errnoval == num_error_names)
+       {
+#ifdef EVMSERR
+         if (strcmp (name, evmserr.name) == 0)
+           errnoval = evmserr.value;
+         else
+#endif
+         errnoval = 0;
+       }
+    }
+  return (errnoval);
+}
+
+
+/* A simple little main that does nothing but print all the errno translations
+   if MAIN is defined and this file is compiled and linked. */
+
+#ifdef MAIN
+
+#include <stdio.h>
+
+int
+main ()
+{
+  int errn;
+  int errnmax;
+  const char *name;
+  char *msg;
+  char *strerror ();
+
+  errnmax = errno_max ();
+  printf ("%d entries in names table.\n", num_error_names);
+  printf ("%d entries in messages table.\n", sys_nerr);
+  printf ("%d is max useful index.\n", errnmax);
+
+  /* Keep printing values until we get to the end of *both* tables, not
+     *either* table.  Note that knowing the maximum useful index does *not*
+     relieve us of the responsibility of testing the return pointer for
+     NULL. */
+
+  for (errn = 0; errn <= errnmax; errn++)
+    {
+      name = strerrno (errn);
+      name = (name == NULL) ? "<NULL>" : name;
+      msg = strerror (errn);
+      msg = (msg == NULL) ? "<NULL>" : msg;
+      printf ("%-4d%-18s%s\n", errn, name, msg);
+    }
+
+  return 0;
+}
+
+#endif
diff --git a/ir/common/tune.h b/ir/common/tune.h
new file mode 100644 (file)
index 0000000..fa88b76
--- /dev/null
@@ -0,0 +1,56 @@
+/* Tune --- tunable parameters.
+   Copyright (C) 1995, 1996 Markus Armbruster & Christian von Roques */
+
+#ifndef _TUNE_H
+#define _TUNE_H
+
+/* From the jargon file:
+
+   :tune: vt.  [from automotive or musical usage] To optimize a
+      program or system for a particular environment, esp. by adjusting
+      numerical parameters designed as {hook}s for tuning, e.g., by
+      changing `#define' lines in C.  One may `tune for time'
+      (fastest execution), `tune for space' (least memory use), or
+      `tune for configuration' (most efficient use of hardware).  See
+      {bum}, {hot spot}, {hand-hacking}.
+
+ */
+
+
+/* Suggested minimal block size for buffered I/O */
+#define TUNE_SMALL_IOBUF_SIZE 512
+
+/* Size of pdeq block cache */
+#define TUNE_NSAVED_PDEQS 16
+
+
+/* The following numbers are only estimates.  If the input exceeds
+   them, the program dynamically enlarges data structures.  However,
+   larger values generally mean slower startup.  */
+
+
+/* Expected number of distinct identifiers */
+#define TUNE_NIDENTS 1024
+
+/* Expected number of classes */
+#define TUNE_NCLASSES 128
+
+/* Expected number of class types */
+#define TUNE_NCTYPES 128
+
+/* Expected number of routine, stream and stream object types */
+#define TUNE_NMTYPES 512
+
+/* Expected number of method families */
+#define TUNE_NMFAMILIES (TUNE_NCTYPES * 16)
+
+/* Expected number of Intermediate Representation nodes for a method */
+#define TUNE_NIR_NODES 512
+
+/* Expected number of distinct constant target values */
+#define TUNE_NCONSTANTS        2048
+
+/* notify configuration manager to prefetch sources */
+#define TUNE_PREFETCH
+
+#endif
diff --git a/ir/common/xfprintf.c b/ir/common/xfprintf.c
new file mode 100644 (file)
index 0000000..a29a961
--- /dev/null
@@ -0,0 +1,69 @@
+/* Xfprintf --- extended formatted output to files.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef USE_PRINTF
+
+#include <assert.h>
+#include "xprintf.h"
+
+
+static int
+xfprinter (void *f, const char *data, size_t len)
+{
+  size_t togo = len;
+
+  while (togo > 0) {
+    size_t n = fwrite (data, 1, togo, (FILE*)f);
+
+    if (!n) return -1;
+    togo -= n;
+    data += n;
+  }
+
+  return len;
+}
+
+
+int
+xfprintf (FILE *F, const char *fmt, ...)
+{
+  va_list args;
+  int res;
+
+  va_start (args, fmt);
+  res = xvgprintf (xfprinter, F, fmt, args);
+  va_end (args);
+  return res;
+}
+
+
+int
+xvfprintf (FILE *F, const char *fmt, va_list args)
+{
+  return xvgprintf (xfprinter, F, fmt, args);
+}
+
+
+int
+xprintf (const char *fmt, ...)
+{
+  va_list args;
+  int res;
+
+  va_start (args, fmt);
+  res = xvgprintf (xfprinter, stdout, fmt, args);
+  va_end (args);
+  return res;
+}
+
+int
+xvprintf (const char *fmt, va_list args)
+{
+  return xvgprintf (xfprinter, stdout, fmt, args);
+}
+
+#endif /* USE_PRINTF */
diff --git a/ir/common/xgprintf.c b/ir/common/xgprintf.c
new file mode 100644 (file)
index 0000000..4ce4c42
--- /dev/null
@@ -0,0 +1,337 @@
+/* Xgprintf --- extended formatted output via generic printer functions.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+/* Implements ANSI-C printf formats minus locale plus extensions,
+   noteably GNU Libc-like registering of specifier-handlers.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef USE_PRINTF
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include "misc.h"
+#include "xprintf.h"
+
+
+/* >= size of ASCII representation of a number using base 8 + 1 */
+#define BUFSIZE ((sizeof(unsigned long)*CHAR_BIT)/3 + 2)
+
+/* For printing double/float numbers, must be large enough for
+   arbitrary numbers with %g.  @@@ Yeek! */
+#define FBUFSIZE 128
+
+static xprintf_function *print_func[UCHAR_MAX+1];
+
+
+void
+xprintf_register (char spec, xprintf_function func)
+{
+  assert ((spec > 0) && !print_func[(unsigned char)spec]);
+  print_func[(unsigned char)spec] = func;
+}
+
+
+int
+xvgprintf (xgprintf_func *out, void *arg, const char *fmt, va_list args)
+{
+  int done;                                            /* number of chars printed */
+  unsigned long num;
+  int is_neg;
+  long signed_num;
+  int base;
+  char c;
+  char fbuf[FBUFSIZE];                 /* buffer for sprintf @@@ Yeek! */
+  char buf[BUFSIZE];                   /* buffer for itoa */
+  char *str;                                   /* buffer pointer for number conversion */
+  const char *s;                               /* string to be printed by string: */
+  int len;                                             /* length of s */
+  char pad;                                            /* padding: ' ' or '0' */
+  int showsign;                                        /* always show sign ['+'] */
+  int space;                                   /* print space if positive */
+  int left;                                            /* left justify */
+  int alt;                                             /* alternate format 0x... */
+  char fc;                                             /* conversion specifier */
+  int width;                                   /* width of output field */
+  int prec;                                            /* min. # of digits for integers; max
+                                                                  number of chars for from string */
+  int qualifier;                               /* 'h', 'l', or 'L' for integer fields */
+
+  done = 0;
+
+#define P(__b,__l) do { out (arg, __b, __l); done += __l; } while (0)
+
+  while (*fmt) {
+    const char *next = strchr (fmt, '%');
+
+    if (!next) {
+      P (fmt, strlen(fmt));
+      break;
+    } else if (next != fmt) {
+      P (fmt, next-fmt);
+      fmt = next;
+    }
+
+    /* Check for "%%".  Note that although the ANSI standard lists
+       '%' as a conversion specifier, it says "The complete format
+       specification shall be `%%'," so we can avoid all the width
+       and prec processing.  */
+    if (fmt[1] == '%') {
+      P (fmt, 1);
+      fmt += 2;
+      continue;
+    }
+
+    /* process flags */
+    is_neg = showsign = space = left = alt = 0;  pad = ' ';
+
+  repeat:
+    ++fmt;                     /* this also skips first '%' */
+    switch (*fmt) {
+    case '-': left = 1; goto repeat;
+    case '+': showsign = 1; goto repeat;
+    case ' ': space = 1; goto repeat;
+    case '#': alt = 1; goto repeat;
+    case '0': pad = '0'; goto repeat;
+    }
+
+    /* get field width */
+    width = 0;
+    if (*fmt == '*') {
+      ++fmt, width = va_arg(args, int);
+      if (width < 0) left = 1, width = -width;
+    } else while (isdigit(*fmt)) width = 10*width + *fmt++ - '0';
+
+    /* get the prec */
+    if (*fmt == '.') {
+      ++fmt;
+      if (*fmt == '*') ++fmt, prec = va_arg(args, int);
+      else { prec = 0; while (isdigit(*fmt)) prec = 10*prec + *fmt++ - '0'; }
+      if (prec < 0) prec = 0;
+    } else prec = -1;          /* -1 == unspecified */
+
+    /* get the conversion qualifier */
+    if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
+      qualifier = *fmt++;
+    else
+      qualifier = -1;
+
+    fc = *fmt++;
+
+    if (print_func[(unsigned char)fc]) {
+      xprintf_info info;
+      int func_done;
+
+      info.prec = prec;
+      info.width = width;
+      info.spec = fc;
+      info.is_long_double = qualifier == 'L';
+      info.is_short       = qualifier == 'h';
+      info.is_long        = qualifier == 'l';
+      info.alt = alt;
+      info.space = space;
+      info.left = left;
+      info.showsign = showsign;
+      info.pad = pad;
+
+      /* Sharing `args' with another function is not blessed by ANSI
+                C.  From ISO/IEC DIS 9899, section 4.4:
+
+                If access to the varying arguments is desired, the called
+                function shall declare an object (referred as `ap' in this
+                section) having type va_list.  The object `ap' may be passed
+                as an argument to another function; if that function invokes
+                the va_arg macro with parameter `ap', the value of `ap' in
+                the calling function is indeterminate and shall be passed to
+                the va_end macro prior to any futher reference to `ap'.
+
+                Nevertheless, it works with most compilers, including gcc.  */
+      func_done = print_func[(unsigned char)fc] (out, arg, &info, &args);
+      if (func_done < 0) return -1;
+      else done += func_done;
+
+    } else {
+
+      /* default base */
+      base = 10;
+
+      switch (fc) {
+
+      case 'c':                        /* Character */
+               { c = (char) va_arg (args, int);
+               s = &c;
+               len = 1;
+               goto string;
+               }
+
+      case 's':                        /* String */
+               { static const char null[] = "(null)";
+               s = va_arg(args, char *);
+               if (!s) {
+                 s = null;
+                 len = (prec == -1 || prec >= (int) sizeof(null) - 1) ? sizeof(null) - 1 : 0;
+               } else {
+                 len = strlen (s);
+               }
+
+               string:
+               if (prec >= 0 && prec < len)
+                 len = prec;
+               width -= len;
+
+               if (!left)
+                 while (width-- > 0)
+                       P (" ", 1);
+               P (s, len);
+               while (width-- > 0)
+                 P (" ", 1);
+               break;
+               }
+      case 'p':                        /* Pointer */
+               {       const char nil[] = "(nil)";
+               const void *ptr = va_arg (args, void *);
+               if (!ptr && (prec==-1 || prec>=(int)sizeof(nil)-1)) {
+                 s = nil;
+                 len = sizeof(nil) - 1;
+                 goto string;
+               }
+
+               base = 16; alt = 1; fc = 'x';
+               num = (unsigned long) ptr;
+               goto number2;
+               }
+
+      case 'o':                        /* Octal */
+               base = 8;
+      case 'u':                        /* Unsigned */
+               goto number;
+
+      case 'X':                        /* heXadecimal */
+      case 'x':                        /* heXadecimal */
+               base = 16;
+      number:                  /* get and print a unsigned number */
+               if (qualifier == 'l')
+                 num = va_arg(args, unsigned long);
+               else if (qualifier == 'h')
+                 num = va_arg(args, unsigned short);
+               else
+                 num = va_arg(args, unsigned int);
+               /* ANSI only specifies the `+' and ` ' flags for signed conversions.  */
+               is_neg = showsign = space = 0;
+               goto number2;
+
+      case 'd':                        /* Decimal */
+      case 'i':                        /* Integer */
+               if (qualifier == 'l')
+                 signed_num = va_arg(args, long);
+               else if (qualifier == 'h')
+                 signed_num = va_arg(args, short);
+               else
+                 signed_num = va_arg(args, int);
+               num = (is_neg = signed_num < 0) ? - signed_num : signed_num;
+
+      number2:                 /* print number in num */
+               {
+                 static const char conv_TABLE[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+                 static const char conv_table[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+                 const char *conv = fc=='X' ? conv_TABLE : conv_table;
+                 str = buf+BUFSIZE;    /* str = _itoa(buf+BUFSIZE,num,base,fc=='X') */
+                 if (!num) *--str = '0';
+                 else do *--str = conv[num % base]; while (num/=base);
+                 len = buf + BUFSIZE - str;
+               }
+
+               /* prepend 0 for octal format. */
+               if (alt && base == 8 && prec<=len) {
+                 *--str = '0';
+                 ++len;
+               }
+
+               /* we will print s ==> cut prec and width */
+               prec -= len;
+               width -= len;
+
+               if (prec > 0) width -= prec; /* we will use all precision space! */
+
+               if (is_neg || showsign || space) --width;
+               if (base == 16 && alt) width -= 2;
+
+               if (!left && pad==' ')
+                 while (width-- > 0) P (" ", 1);
+
+               if (is_neg)
+                 P ("-", 1);
+               else if (showsign)
+                 P ("+", 1);
+               else if (space)
+                 P (" ", 1);
+
+               if (base == 16 && alt) {
+                 P ("0", 1);
+                 P (&fc, 1);
+               }
+
+               if (!left && pad=='0')
+                 while (width-- > 0) P ("0", 1);
+
+               while (prec-- > 0) P ("0", 1);
+
+               P (str, len);
+
+               while (width-- > 0)  P (" ", 1);
+               break;
+
+               /* @@@ NYI (just hacked) */
+      case 'e':
+      case 'E':
+      case 'f':
+      case 'g':
+      case 'G':
+#ifdef HAVE_ANSI_SPRINTF
+               len = sprintf (fbuf, "%g", va_arg (args, double));
+#else
+               sprintf (fbuf, "%g", va_arg (args, double));
+               len = strlen (fbuf);
+#endif
+               s = fbuf;
+               goto string;
+
+      case 'n':                        /* assign #printed characters */
+               if (qualifier == 'l')           *va_arg (args, long *) = done;
+               else if (qualifier == 'h')      *va_arg (args, short *) = done;
+               else { assert (qualifier == -1); *va_arg (args, int *) = done; }
+               break;
+
+      case 'm':                        /* errno, GNU extension */
+               /* strerror() is ANSI C, sys_nerr & sys_errlist are not */
+               s = strerror (errno);
+               len = strlen (s);
+               goto string;
+
+      default:
+               assert (0);
+      }
+    }
+  }
+  return done;
+}
+
+
+int
+xgprintf (xgprintf_func *out, void *arg, const char *fmt, ...)
+{
+  va_list args;
+  int i;
+
+  va_start (args, fmt);
+  i = xvgprintf (out, arg, fmt, args);
+  va_end (args);
+  return i;
+}
+
+#endif /* !USE_PRINTF */
diff --git a/ir/common/xoprintf.c b/ir/common/xoprintf.c
new file mode 100644 (file)
index 0000000..bc096a7
--- /dev/null
@@ -0,0 +1,43 @@
+/* Xfprintf --- extended formatted output to obstacks.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef USE_PRINTF
+
+#include <obstack.h>
+#include <string.h>
+#include <assert.h>
+#include "xprintf.h"
+
+
+static int
+xoprinter (void *obst, const char *data, size_t len)
+{
+  obstack_grow ((struct obstack *)obst, data, len);
+  return len;
+}
+
+
+int
+xoprintf (struct obstack *obst, const char *fmt, ...)
+{
+  va_list args;
+  int res;
+
+  va_start (args, fmt);
+  res = xvgprintf (xoprinter, obst, fmt, args);
+  va_end (args);
+  return res;
+}
+
+
+int
+xvoprintf (struct obstack *obst, const char *fmt, va_list args)
+{
+  return xvgprintf (xoprinter, obst, fmt, args);
+}
+
+#endif /* USE_PRINTF */
diff --git a/ir/common/xp_help.h b/ir/common/xp_help.h
new file mode 100644 (file)
index 0000000..a57c581
--- /dev/null
@@ -0,0 +1,40 @@
+/* Macros to help writing output handlers.
+   Copyright (C) 1996 Markus Armbruster */
+
+#ifndef _XP_HELP_H
+#define _XP_HELP_H
+
+# ifdef HAVE_STRING_H
+#  include <string.h>
+# endif
+#ifdef USE_PRINTF
+# define XP_ARG1 stream
+# define XP_ARGN args
+# define XP_GETARG(type, index) (*(type *)args[index])
+# define XPMR(p,n) fwrite ((p), 1, (n), stream)
+# define XPR(p) fputs ((p), stream)
+# define XPF1R(fmt, arg) fprintf (stream, (fmt), (arg))
+# define XPCR(p) (putc (*(p), stream) == EOF ? -1 : 1)
+#else /* !USE_PRINTF */
+# define XP_ARG1 f, a
+# define XP_ARGN ap
+# define XP_GETARG(type, index) va_arg (*ap, type)
+# define XPMR(p,n) f (a, (p), (n))
+# define XPR(p) f (a, (p), strlen((p)))
+# define XPF1R(fmt, arg) xgprintf (f, a, (fmt), (arg))
+# define XPCR(p) XPMR (p, 1)
+#endif /* !USE_PRINTF */
+
+#define XP(p) XP_CHK (XPR ((p)))
+#define XPM(p,n) XP_CHK (XPMR ((p), (n)))
+#define XPSR(p) XPMR ((p), sizeof(p)-1)
+#define XPS(p) XPM ((p), sizeof(p)-1)
+#define XPF1(fmt, arg) XP_CHK (XPF1R ((fmt), (arg)))
+#define XPC(c) XP_CHK (XPCR ((c)))
+#define XP_CHK(expr)                           \
+  do {                                         \
+    int n = (expr);                            \
+    if (n < 0) return -1; else printed += n;   \
+  } while (0)
+
+#endif
diff --git a/ir/common/xprintf.h b/ir/common/xprintf.h
new file mode 100644 (file)
index 0000000..c137278
--- /dev/null
@@ -0,0 +1,106 @@
+/* Declarations for xprintf & friends.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+/* Parts of this file are adapted from the GNU C Library.
+Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef _XPRINTF_H_
+#define _XPRINTF_H_
+
+#ifdef USE_PRINTF
+
+/* This code is just an incomplete sketch how GNU libc could be used,
+   if it provided the necessary functionality.  Problems:
+   o  obstack_printf() is not yet available, it will be in version 2.
+   o  User defined conversion specifiers cannot take struct arguments.
+   Using GNU libc should be *significantly* faster.  */
+
+# include <printf.h>
+
+# define XP_PAR1 FILE *stream
+# define XP_PARN const void **args
+
+typedef struct printf_info xprintf_info;
+
+/* @@@ GNU libc version 2's register_printf_function *requires*
+   non-NULL 3rd argument */
+# define xprintf_register(spec, func) \
+    register_printf_function ((spec), (func), NULL)
+
+# define xprintf printf
+# define xvprintf vprintf
+# define xfprintf fprintf
+# define xvfprintf vfprintf
+# define xoprintf obstack_printf
+# define xvoprintf obstack_vprintf
+
+#else /* !USE_PRINTF */
+
+/* Emulate GNU libc functionality on top of standard libc */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+
+
+# define XP_PAR1 xgprintf_func *f, void *a
+# define XP_PARN va_list *ap
+
+/* Type of a generic print function */
+typedef int xgprintf_func (void *, const char *, size_t);
+
+typedef struct
+{
+  int prec;                    /* Precision.  */
+  int width;                   /* Width.  */
+  unsigned char spec;          /* Format letter.  */
+  unsigned int is_long_double:1;/* L flag.  */
+  unsigned int is_short:1;     /* h flag.  */
+  unsigned int is_long:1;      /* l flag.  */
+  unsigned int alt:1;          /* # flag.  */
+  unsigned int space:1;                /* Space flag.  */
+  unsigned int left:1;         /* - flag.  */
+  unsigned int showsign:1;     /* + flag.  */
+  char pad;                    /* Padding character.  */
+} xprintf_info;
+
+/* Type of a printf specifier-handler function.
+   `printer' is the generic print function to be called with first
+   argument `out'.  `info' gives information about the format
+   specification.  Arguments can be read from `args'.  The function
+   shall return the number of characters written, or -1 for errors.  */
+typedef int xprintf_function (xgprintf_func *printer, void *out,
+                             const xprintf_info *info,
+                             va_list *args);
+
+void xprintf_register (char spec, xprintf_function *);
+
+int xgprintf(xgprintf_func *, void *, const char *, ...);
+int xvgprintf(xgprintf_func *, void *, const char *, va_list);
+
+int xprintf (const char *, ...);
+int xvprintf (const char *, va_list);
+int xfprintf (FILE *, const char *, ...);
+int xvfprintf (FILE *, const char *, va_list);
+
+struct obstack;
+int xoprintf (struct obstack *, const char *, ...);
+int xvoprintf (struct obstack *, const char *, va_list);
+
+#endif /* !USE_PRINTF */
+#endif /* _XPRINTF_H_ */
diff --git a/ir/debug/Makefile b/ir/debug/Makefile
new file mode 100644 (file)
index 0000000..f71bc14
--- /dev/null
@@ -0,0 +1,60 @@
+# Hey, emacs, this is a -*- makefile -*-
+## Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Makefile for debug -- debugging of compiler or compiled program??
+
+
+CXX         = gcc
+CFLAGS      = -pipe -Wall # -ansi -pedantic
+CXXFLAGS    = # -g
+COPTFLAGS   = -O3
+LDFLAGS     =
+DEPENDFLAGS = -M
+LIBPATH     =
+LIBS        =
+X_LIBS      =
+INCLUDES    = -I../adt -I../common -I../debug
+X_INCLUDES  =
+
+AR          = ar rcs
+
+SHELL       = /bin/sh
+MAKE        = /usr/bin/make
+
+MEMBERS         = debug.m
+
+CFILES = $(MEMBERS:.m=.c)
+
+HFILES = $(MEMBERS:.m=.h)
+HFILES +=  misc.h host.h
+
+OFILES = $(MEMBERS:%.m=../objects/%.o)
+
+DFILES = $(MEMBERS:.m=.d)
+
+TARGET = all
+
+.PHONY: default all clean realclean install depend
+.SUFFIXES: .d .h .c .o
+.DEFAULT: $(TARGET)
+.SILENT: $(DFILES) clean  # hides output
+
+%.d:    %.c
+       $(SHELL) -ec '$(CXX) $(DEPENDFLAGS) $(INCLUDES) $(X_INCLUDES) $< | sed '\''s/\($*\)\.o[ :]*/\.\.\/objects\/\1.o $@ : /g'\'' > $@'
+
+
+../objects/%.o:    %.c
+       $(CXX) $(CFLAGS) $(CXXFLAGS) $(COPTFLAGS) $(INCLUDES) $(X_INCLUDES) -c $< -o $@
+
+
+$(TARGET):      $(DFILES) $(OFILES)
+
+clean:
+       rm -f $(OFILES) $(DFILES)
+
+realclean:     clean
+       rm -f $(TARGET) *.flc TAGS
+
+-include $(DFILES)
diff --git a/ir/debug/debug.c b/ir/debug/debug.c
new file mode 100644 (file)
index 0000000..00740db
--- /dev/null
@@ -0,0 +1,91 @@
+/* Debug --- run time debug level management
+   Copyright (C) 1995, 1996 Christian von Roques
+   All rights reserved. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "debug.h"
+#include "misc.h"
+
+
+int
+(d_) (int flag, unsigned level)
+{
+  return d_ (flag, level);
+}
+
+
+int
+(d_level) (int flag)
+{
+  return d_level (flag);
+}
+
+
+int
+(d_set_level) (int flag, unsigned level)
+{
+  return d_set_level (flag, level);
+}
+
+
+#ifdef DEBUG
+int nflags;
+unsigned char *d_vec;
+#endif
+
+
+/*
+ * Set debug flags according to the following syntax:
+ * number ["-" number] ["." number]
+ * 1st number is number of first flag to set.
+ * 2nd number is number of last flag to set. [defaults to 1st number]
+ * 3rd number is level to set the flags to. [defaults to 1]
+ */
+void
+(d_parse) (const char *s)
+{
+#ifdef DEBUG
+  long first, last, level;
+  char *end;
+
+  first = strtol(s, &end, 10);
+  last = (s != end) ? first : nflags-1;
+
+  s = end;
+  if (*s == '-') {
+    ++s;
+    last = strtol(s, &end, 10);
+    if (end == s) last = nflags-1; /* 3-  ==> 3..nflags-1 */
+  }
+
+  s = end;
+  if (*s == '.') {
+    ++s;
+    level = strtol(s, &end, 10);
+    /* . with no number gives level 0 */
+  } else {
+    level = 1;
+  }
+
+  if (first<0) first=0;
+  if (last>=nflags) last = nflags-1;
+
+  while (first<=last) d_vec[first++] = level;
+#endif /* DEBUG */
+}
+
+
+void
+(d_init) (int n)
+{
+#ifdef DEBUG
+  nflags = n;
+  d_vec = xmalloc (sizeof (unsigned char) * n);
+  memset(d_vec, 0, sizeof (unsigned char) * n);
+#endif
+}
diff --git a/ir/debug/debug.h b/ir/debug/debug.h
new file mode 100644 (file)
index 0000000..89c1392
--- /dev/null
@@ -0,0 +1,36 @@
+/* Declarations for debug
+   Copyright (C) 1995, 1996 Christian von Roques
+   All rights reserved.  */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+void d_init (int nflags);
+int d_ (int flag, unsigned level);
+int d_level (int flag);
+int d_set_level (int flag, unsigned level);
+void d_parse (const char *s);
+
+#ifdef DEBUG
+
+#include "deflag.h"
+
+extern unsigned char *d_vec;
+
+# define d_init(n) (d_init) ((n))
+# define d_(flag, level) (d_vec[(flag)] >= (level))
+# define d_level(flag) (d_vec[(flag)])
+# define d_set_level(flag, level) (d_vec[(flag)] = (level))
+# define d_parse(s) (d_parse) ((s))
+
+#else  /* !DEBUG */
+
+# define d_init(n) ((void)0)
+# define d_(flag, level) 0
+# define d_level(flag) 0
+# define d_set_level(flag, level) (level)
+# define d_parse(s) ((void)0)
+
+#endif /* !DEBUG */
+
+#endif
diff --git a/ir/ident/Makefile b/ir/ident/Makefile
new file mode 100644 (file)
index 0000000..4987b58
--- /dev/null
@@ -0,0 +1,60 @@
+# Hey, emacs, this is a -*- makefile -*-
+#
+# Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Makefile for ident -- ??
+
+CXX         = gcc
+CFLAGS      = -pipe -Wall # -ansi -pedantic
+CXXFLAGS    = # -g
+COPTFLAGS   = -O3
+LDFLAGS     =
+DEPENDFLAGS = -M
+LIBPATH     =
+LIBS        =
+X_LIBS      =
+INCLUDES    = -I../adt -I../common -I../debug -I../ident
+X_INCLUDES  =
+
+SHELL       = /bin/sh
+MAKE        = /usr/bin/make
+
+MEMBERS         = ident.m
+
+CFILES = $(MEMBERS:.m=.c)
+
+HFILES = $(MEMBERS:.m=.h)
+HFILES +=  xx_ident.h
+HFILES += array.h cookies.h debug.h host.h misc.h set.h tune.h xprintf.h \
+         xp_help.h
+
+OFILES = $(MEMBERS:%.m=../objects/%.o)
+
+DFILES = $(MEMBERS:.m=.d)
+
+TARGET = all
+
+.PHONY: default all clean realclean install depend
+.SUFFIXES: .d .h .c .o
+.DEFAULT: $(TARGET)
+.SILENT: $(DFILES) clean  # hides output
+
+%.d:    %.c
+       $(SHELL) -ec '$(CXX) $(DEPENDFLAGS) $(INCLUDES) $(X_INCLUDES) $< | sed '\''s/\($*\)\.o[ :]*/\.\.\/objects\/\1.o $@ : /g'\'' > $@'
+
+
+../objects/%.o:    %.c
+       $(CXX) $(CFLAGS) $(CXXFLAGS) $(COPTFLAGS) $(INCLUDES) $(X_INCLUDES) -c $< -o $@
+
+
+$(TARGET):      $(DFILES) $(OFILES)
+
+clean:
+       rm -f $(OFILES) $(DFILES)
+
+realclean:     clean
+       rm -f $(TARGET) *.flc TAGS
+
+-include $(DFILES)
diff --git a/ir/ident/ident.c b/ir/ident/ident.c
new file mode 100644 (file)
index 0000000..623a208
--- /dev/null
@@ -0,0 +1,97 @@
+/* Ident --- unique handles for identifiers
+   Copyright (C) 1995, 1996 Markus Armbruster
+   All rights reserved. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include "array.h"
+#include "tune.h"
+#include "ident.h"
+#include "xprintf.h"
+
+#define XX_USER(name) ident *id_##name;
+#define XX_INTERNAL(name, str) XX_USER(name)
+#include "xx_ident.h"
+#undef XX_USER
+#undef XX_INTERNAL
+
+set *id_set;
+
+
+ident *
+new_id_derived (const char *pfx, ident *id)
+{
+  int pfx_len = strlen (pfx);
+  int len = pfx_len + ID_TO_STRLEN (id);
+  char *str = alloca (len);
+
+  memcpy (str, pfx, pfx_len);
+  memcpy (str+pfx_len, ID_TO_STR (id), ID_TO_STRLEN (id));
+  return ID_FROM_STR (str, pfx_len + ID_TO_STRLEN (id));
+}
+
+
+ident *
+new_id_internal (void)
+{
+  static char str[] = "_0000000";
+  int i;
+
+  i = sizeof (str) - 2;
+  while (++str[i] == '9'+1) {
+    str[i--] = '0';
+    /* if following assertion fails, we get called far too often ;-) */
+    assert (i >= 0);
+  }
+  assert (('0' <= str[i]) && (str[i] <= '9'));
+
+  return ID_FROM_STR (str, sizeof (str) - 1);
+}
+
+
+bool
+id_is_internal (ident *id)
+{
+  assert (ID_TO_STRLEN (id));
+  return !!ispunct (ID_TO_STR(id)[0]);
+}
+
+
+#ifndef NDEBUG
+
+void
+ids_vrfy (ident **id)
+{
+  int i;
+
+  for (i = 0;  i < ARR_LEN (id);  ++i) {
+    ID_VRFY (id[i]);
+  }
+}
+
+#endif
+
+int
+ident_print (XP_PAR1, const xprintf_info *info ATTRIBUTE((unused)), XP_PARN)
+{
+  ident *id = XP_GETARG (ident *, 0);
+  return XPMR (ID_TO_STR (id), ID_TO_STRLEN (id));
+}
+
+
+void
+id_init (void)
+{
+  id_set = new_set (memcmp, TUNE_NIDENTS);
+
+#define XX_USER(name) id_##name = ID_FROM_STR(#name, sizeof(#name)- 1);
+#define XX_INTERNAL(name, str) id_##name = ID_FROM_STR((str), sizeof((str))-1);
+#include "xx_ident.h"
+#undef XX_USER
+#undef XX_INTERNAL
+}
diff --git a/ir/ident/ident.h b/ir/ident/ident.h
new file mode 100644 (file)
index 0000000..fb8edda
--- /dev/null
@@ -0,0 +1,75 @@
+/* Declarations for ident.
+   Copyright (C) 1995, 1996 Markus Armbruster */
+
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+*/
+
+# ifndef _IDENT_H_
+# define _IDENT_H_
+
+#include <assert.h>
+#include <stddef.h>
+#include "misc.h"
+#include "debug.h"
+#include "set.h"
+
+# include "xprintf.h"
+# include "xp_help.h"
+
+/* Identifiers */
+typedef const struct set_entry ident;
+
+/* Caution: strings _not_ zero-terminated! */
+#define ID_FROM_STR(str, len) \
+  (assert ((len) > 0), \
+   (const set_entry *)set_hinsert (id_set, (str), (len), ID_HASH ((str), (len))))
+#define ID_TO_STR(id) ((const char *)&(id)->dptr[0])
+#define ID_TO_STRLEN(id) ((id)->size)
+#define ID_TO_HASH(id) ((long)(id) + (id)->hash)
+
+ident *new_id_derived (const char *pfx, ident *);
+ident *new_id_internal (void);
+bool id_is_internal (ident *);
+void id_init (void);
+
+#ifdef NDEBUG
+# define ID_VRFY(id) ((void)0)
+# define IDS_VRFY(id) ((void)0)
+#else
+# define ID_VRFY(id) \
+    assert (   (id) \
+           && (   !d_ (df_vrfy_level, 1) \
+               || (ID_FROM_STR (ID_TO_STR((id)), ID_TO_STRLEN((id))) == (id))))
+# define IDS_VRFY(id) ids_vrfy ((id))
+void ids_vrfy (ident **id);
+#endif
+
+#ifdef STATS
+# define id_stats() set_stats (id_set)
+#else
+# define id_stats() ((void)0)
+#endif
+
+/* Private */
+
+/* @@@ tune */
+#define ID_HASH(str, len) \
+  (((  ((unsigned char *)(str))[0] * 33 \
+     + ((unsigned char *)(str))[(len)>>1]) * 31 \
+    + ((unsigned char *)(str))[(len)-1]) * 9 \
+   + (len))
+
+extern set *id_set;
+
+
+# define id_from_str  ID_FROM_STR
+# define id_to_str    ID_TO_STR
+# define id_to_strlen ID_TO_STRLEN
+
+
+int ident_print (XP_PAR1, const xprintf_info *, XP_PARN);
+
+# endif /* _IDENT_H_ */
diff --git a/ir/ident/xx_ident.h b/ir/ident/xx_ident.h
new file mode 100644 (file)
index 0000000..f086878
--- /dev/null
@@ -0,0 +1,8 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+/* XX_USER (Add) */
diff --git a/ir/ir/INTERMEDIATE_REPRESENTATION b/ir/ir/INTERMEDIATE_REPRESENTATION
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ir/ir/Makefile b/ir/ir/Makefile
new file mode 100644 (file)
index 0000000..844e21a
--- /dev/null
@@ -0,0 +1,64 @@
+# Hey, emacs, this is a -*- makefile -*-
+#
+# Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Makefile for ir -- intermediate representation of the program
+
+CXX         = gcc
+CFLAGS      = -pipe -Wall # -ansi -pedantic
+CXXFLAGS    = # -g
+COPTFLAGS   = -O3
+LDFLAGS     =
+DEPENDFLAGS = -M
+LIBPATH     =
+LIBS        =
+X_LIBS      =
+INCLUDES    = -I../adt -I../common -I../debug -I../ident -I../include \
+             -I../ir -I../tr -I../tv
+X_INCLUDES  =
+
+SHELL       = /bin/sh
+MAKE        = /usr/bin/make
+
+MEMBERS         = ircons.m irdump.m irflag.m irgmod.m irgraph.m \
+           irgwalk.m irmode.m irnode.m irop.m iropt.m irvrfy.m
+
+CFILES = $(MEMBERS:.m=.c)
+
+HFILES = $(MEMBERS:.m=.h)
+HFILES +=  array.h common.h cookies.h debug.h entity.h gmp.h  \
+           host.h ident.h label.h misc.h obst.h pdeq.h pset.h \
+           set.h tune.h tv.h type.h xprintf.h xp_help.h
+
+OFILES = $(MEMBERS:%.m=../objects/%.o)
+
+DFILES = $(MEMBERS:.m=.d)
+
+TARGET = all
+
+.PHONY: default all clean realclean install depend
+.SUFFIXES: .d .h .c .o
+.DEFAULT: $(TARGET)
+.SILENT: $(DFILES) clean  # hides output
+
+
+$(TARGET): $(DFILES) $(OFILES)
+
+# the preprocessor computes the dependencies and saves them to a file
+# the sed script adds the path to ../objects and file.d to the dependency.
+%.d:   %.c
+       $(SHELL) -ec '$(CXX) $(DEPENDFLAGS) $(INCLUDES) $(X_INCLUDES) $< | sed '\''s/\($*\)\.o[ :]*/\.\.\/objects\/\1.o $@ : /g'\'' > $@'
+
+
+../objects/%.o:        %.c
+       $(CXX) $(CFLAGS) $(CXXFLAGS) $(COPTFLAGS) $(INCLUDES) $(X_INCLUDES) -c $< -o $@
+
+clean:
+       rm -f $(OFILES) $(DFILES)
+
+realclean:     clean
+       rm -f $(TARGET) *.flc TAGS
+
+-include $(DFILES)
diff --git a/ir/ir/ircons.c b/ir/ir/ircons.c
new file mode 100644 (file)
index 0000000..83746c4
--- /dev/null
@@ -0,0 +1,1062 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** ircons.c: basic and more detailed irnode constructors
+**           store, block and parameter administration ,
+** Adapted to extended FIRM nodes (exceptions...) and commented
+**   by Goetz Lindenmaier
+*/
+
+# include "ircons.h"
+# include "array.h"
+# include "iropt.h"
+/* memset belongs to string.h */
+# include "string.h"
+
+
+/* irnode constructor                                             */
+/* create a new irnode in irg, with an op, mode, arity and        */
+/* some incoming irnodes                                          */
+/* this constructor is used in every specified irnode constructor */
+inline ir_node *
+new_ir_node (ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mode,
+            int arity, ir_node **in)
+{
+  ir_node *res;
+  int node_size = offsetof (ir_node, attr) +  op->attr_size;
+
+  res = (ir_node *) obstack_alloc (irg->obst, node_size);
+
+  res->kind = k_ir_node;
+  res->op = op;
+  res->mode = mode;
+  res->visit = 0;
+  res->link = NULL;
+  if (arity < 0) {
+    res->in = NEW_ARR_F (ir_node *, 1);
+  } else {
+    res->in = NEW_ARR_D (ir_node *, irg->obst, (arity+1));
+    memcpy (&res->in[1], in, sizeof (ir_node *) * arity);
+  }
+  res->in[0] = block;
+  return res;
+}
+
+
+
+
+/*********************************************** */
+/** privat interfaces, for professional use only */
+
+/* Creates a Phi node with 0 predecessors */
+inline ir_node *
+new_r_Phi0 (ir_graph *irg, ir_node *block, ir_mode *mode)
+{
+  ir_node *res;
+
+  res = new_ir_node (irg, block, op_Phi, mode, 0, NULL);
+
+  /* GL I'm not sure whether we should optimize this guy. *
+     res = optimize (res); ??? */
+  ir_vrfy (res);
+  return res;
+}
+
+/* Creates a Phi node with all predecessors.  Calling this constructor
+   is only allowed if the corresponding block is mature.  */
+ir_node *
+new_r_Phi (ir_graph *irg, ir_node *block, int arity, ir_node **in, ir_mode *mode)
+{
+  ir_node *res;
+
+  assert( get_Block_matured(block) );
+  assert( get_irn_arity(block) == arity );
+
+  res = new_ir_node (irg, block, op_Phi, mode, arity, in);
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+/* This is a stack used for allocating and deallocating nodes in
+   new_r_Phi_in.  The original implementation used the obstack
+   to model this stack, now it is explicit.  This reduces side effects.
+*/
+#if USE_EXPICIT_PHI_IN_STACK
+Phi_in_stack *
+new_Phi_in_stack() {
+  Phi_in_stack *res;
+
+  res = (Phi_in_stack *) malloc ( sizeof (Phi_in_stack));
+
+  res->stack = NEW_ARR_F (ir_node *, 1);
+  res->pos = 0;
+
+  return res;
+}
+
+
+void free_to_Phi_in_stack(ir_node *phi) {
+  assert(get_irn_opcode(phi) == iro_Phi);
+
+  if (ARR_LEN(current_ir_graph->Phi_in_stack->stack) ==
+      current_ir_graph->Phi_in_stack->pos)
+    ARR_APP1 (ir_node *, current_ir_graph->Phi_in_stack->stack, phi);
+  else
+    current_ir_graph->Phi_in_stack->stack[current_ir_graph->Phi_in_stack->pos] = phi;
+
+  (current_ir_graph->Phi_in_stack->pos)++;
+}
+
+ir_node *
+alloc_or_pop_from_Phi_in_stack(ir_graph *irg, ir_node *block, ir_mode *mode,
+            int arity, ir_node **in) {
+  ir_node *res;
+  ir_node **stack = current_ir_graph->Phi_in_stack->stack;
+  int pos = current_ir_graph->Phi_in_stack->pos;
+
+
+  if (pos == 0) {
+    /* We need to allocate a new node */
+    res = new_ir_node (irg, block, op_Phi, mode, arity, in);
+  } else {
+    /* reuse the old node and initialize it again. */
+    res = stack[pos-1];
+
+    assert (res->kind == k_ir_node);
+    assert (res->op == op_Phi);
+    res->mode = mode;
+    res->visit = 0;
+    res->link = NULL;
+    assert (arity >= 0);
+    /* ???!!! How to free the old in array??  */
+    res->in = NEW_ARR_D (ir_node *, irg->obst, (arity+1));
+    res->in[0] = block;
+    memcpy (&res->in[1], in, sizeof (ir_node *) * arity);
+
+    (current_ir_graph->Phi_in_stack->pos)--;
+  }
+  return res;
+}
+#endif
+
+
+
+/* Creates a Phi node with a given, fixed array **in of predecessors.
+   If the Phi node is unnecessary, as the same value reaches the block
+   through all control flow paths, it is eliminated and the value
+   returned directly.  This constructor is only intended for use in
+   the automatic Phi node generation triggered by get_value or mature.
+   The implementation is quite tricky and depends on the fact, that
+   the nodes are allocated on a stack:
+   The in array contains predecessors and NULLs.  The NULLs appear,
+   if get_r_value_internal, that computed the predecessors, reached
+   the same block on two paths.  In this case the same value reaches
+   this block on both paths, there is no definition in between.  We need
+   not allocate a Phi where these path's merge, but we have to communicate
+   this fact to the caller.  This happens by returning a pointer to the
+   node the caller _will_ allocate.  (Yes, we predict the address. We can
+   do so because the nodes are allocated on the obstack.)  The caller then
+   finds a pointer to itself and, when this routine is called again,
+   eliminates itself.
+   */
+inline ir_node *
+new_r_Phi_in (ir_graph *irg, ir_node *block, ir_mode *mode,
+             ir_node **in, int ins)
+{
+  int i;
+  ir_node *res, *known;
+
+  /* allocate a new node on the obstack.
+     This can return a node to which some of the pointers in the in-array
+     already point.
+     Attention: the constructor copies the in array, i.e., the later changes
+     to the array in this routine do not affect the constructed node!  If
+     the in array contains NULLs, there will be missing predecessors in the
+     returned node.
+     Is this a possible internal state of the Phi node generation? */
+#if USE_EXPICIT_PHI_IN_STACK
+  res = known = alloc_or_pop_from_Phi_in_stack(irg, block, mode, ins, in);
+#else
+  res = known = new_ir_node (irg, block, op_Phi, mode, ins, in);
+#endif
+  /* The in-array can contain NULLs.  These were returned by get_r_value_internal
+     if it reached the same block/definition on a second path.
+     The NULLs are replaced by the node itself to simplify the test in the
+     next loop. */
+  for (i=0;  i < ins;  ++i)
+    if (in[i] == NULL) in[i] = res;
+
+  /* This loop checks whether the Phi has more than one predecessor.
+     If so, it is a real Phi node and we break the loop.  Else the
+     Phi node merges the same definition on several paths and therefore
+     is not needed. */
+  for (i=0;  i < ins;  ++i)
+  {
+    if (in[i]==res || in[i]==known) continue;
+
+    if (known==res)
+      known = in[i];
+    else
+      break;
+  }
+
+  /* i==ins: there is at most one predecessor, we don't need a phi node. */
+  if (i==ins) {
+#if USE_EXPICIT_PHI_IN_STACK
+    free_to_Phi_in_stack(res);
+#else
+    obstack_free (current_ir_graph->obst, res);
+#endif
+    res = known;
+  } else {
+    res = optimize (res);
+    ir_vrfy (res);
+  }
+
+  /* return the pointer to the Phi node.  This node might be deallocated! */
+  return res;
+}
+
+ir_node *
+new_r_Const (ir_graph *irg, ir_node *block, ir_mode *mode, tarval *con)
+{
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Const, mode, 0, NULL);
+  res->attr.con = con;
+  res = optimize (res);
+  ir_vrfy (res);
+
+#if 0
+  res = local_optimize_newby (res);
+# endif
+
+  return res;
+}
+
+ir_node *
+new_r_Id (ir_graph *irg, ir_node *block, ir_node *val, ir_mode *mode)
+{
+  ir_node *in[1] = {val};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Id, mode, 1, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+ir_node *
+new_r_Proj (ir_graph *irg, ir_node *block, ir_node *arg, ir_mode *mode, long proj)
+{
+  ir_node *in[1] = {arg};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Proj, mode, 1, in);
+  res->attr.proj = proj;
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+
+}
+
+ir_node *
+new_r_Conv (ir_graph *irg, ir_node *block, ir_node *op, ir_mode *mode)
+{
+  ir_node *in[1] = {op};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Conv, mode, 1, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+
+}
+
+ir_node *
+new_r_Tuple (ir_graph *irg, ir_node *block, int arity, ir_node **in)
+{
+  ir_node *res;
+
+  res = new_ir_node (irg, block, op_Tuple, mode_T, arity, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Add (ir_graph *irg, ir_node *block,
+          ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  ir_node *in[2] = {op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Add, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Sub (ir_graph *irg, ir_node *block,
+          ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  ir_node *in[2] = {op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Sub, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Minus (ir_graph *irg, ir_node *block,
+            ir_node *op,  ir_mode *mode)
+{
+  ir_node *in[1] = {op};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Minus, mode, 1, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Mul (ir_graph *irg, ir_node *block,
+          ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  ir_node *in[2] = {op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Mul, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Quot (ir_graph *irg, ir_node *block,
+           ir_node *memop, ir_node *op1, ir_node *op2)
+{
+  ir_node *in[3] = {memop, op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Quot, mode_T, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_DivMod (ir_graph *irg, ir_node *block,
+             ir_node *memop, ir_node *op1, ir_node *op2)
+{
+  ir_node *in[3] = {memop, op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_DivMod, mode_T, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Div (ir_graph *irg, ir_node *block,
+          ir_node *memop, ir_node *op1, ir_node *op2)
+{
+  ir_node *in[3] = {memop, op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Div, mode_T, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Mod (ir_graph *irg, ir_node *block,
+          ir_node *memop, ir_node *op1, ir_node *op2)
+{
+  ir_node *in[3] = {memop, op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Mod, mode_T, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_And (ir_graph *irg, ir_node *block,
+          ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  ir_node *in[2] = {op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_And, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Or (ir_graph *irg, ir_node *block,
+         ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  ir_node *in[2] = {op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Or, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Eor (ir_graph *irg, ir_node *block,
+         ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  ir_node *in[2] = {op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Eor, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Not    (ir_graph *irg, ir_node *block,
+             ir_node *op, ir_mode *mode)
+{
+  ir_node *in[1] = {op};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Not, mode, 1, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Shl (ir_graph *irg, ir_node *block,
+         ir_node *op, ir_node *k, ir_mode *mode)
+{
+  ir_node *in[2] = {op, k};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Shl, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Shr (ir_graph *irg, ir_node *block,
+          ir_node *op, ir_node *k, ir_mode *mode)
+{
+  ir_node *in[2] = {op, k};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Shr, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Shrs (ir_graph *irg, ir_node *block,
+          ir_node *op, ir_node *k, ir_mode *mode)
+{
+  ir_node *in[2] = {op, k};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Shrs, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Rot (ir_graph *irg, ir_node *block,
+          ir_node *op, ir_node *k, ir_mode *mode)
+{
+  ir_node *in[2] = {op, k};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Rot, mode, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Abs (ir_graph *irg, ir_node *block,
+          ir_node *op, ir_mode *mode)
+{
+  ir_node *in[1] = {op};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Abs, mode, 1, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Cmp (ir_graph *irg, ir_node *block,
+          ir_node *op1, ir_node *op2)
+{
+  ir_node *in[2] = {op1, op2};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Cmp, mode_T, 2, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Jmp (ir_graph *irg, ir_node *block)
+{
+  ir_node *in[0] = {};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Jmp, mode_X, 0, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Cond (ir_graph *irg, ir_node *block, ir_node *c)
+{
+  ir_node *in[1] = {c};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Cond, mode_T, 1, in);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+ir_node *
+new_r_Call (ir_graph *irg, ir_node *block, ir_node *store,
+           ir_node *callee, int arity, ir_node **in, type_method *type)
+{
+  ir_node **r_in;
+  ir_node *res;
+  int r_arity;
+
+  r_arity = arity+2;
+  NEW_ARR_A (ir_node *, r_in, r_arity);
+  r_in[0] = store;
+  r_in[1] = callee;
+  memcpy (&r_in[2], in, sizeof (ir_node *) * arity);
+
+  res = new_ir_node (irg, block, op_Call, mode_T, r_arity, r_in);
+
+  set_Call_type(res, type);
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+ir_node *
+new_r_Return (ir_graph *irg, ir_node *block,
+              ir_node *store, int arity, ir_node **in)
+{
+  ir_node **r_in;
+  ir_node *res;
+  int r_arity;
+
+  r_arity = arity+1;
+
+  NEW_ARR_A (ir_node *, r_in, r_arity);
+
+  r_in[0] = store;
+
+  memcpy (&r_in[1], in, sizeof (ir_node *) * arity);
+
+  res = new_ir_node (irg, block, op_Return, mode_X, r_arity, r_in);
+
+  res = optimize (res);
+
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Raise (ir_graph *irg, ir_node *block, ir_node *store, ir_node *obj)
+{
+  ir_node *in[2] = {store, obj};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Raise, mode_X, 2, in);
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Load (ir_graph *irg, ir_node *block,
+           ir_node *store, ir_node *adr)
+{
+  ir_node *in[2] = {store, adr};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Load, mode_T, 2, in);
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Store (ir_graph *irg, ir_node *block,
+            ir_node *store, ir_node *adr, ir_node *val)
+{
+  ir_node *in[3] = {store, adr, val};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Store, mode_T, 3, in);
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Alloc (ir_graph *irg, ir_node *block, ir_node *store,
+           ir_node *size, type *alloc_type, where_alloc where)
+{
+  ir_node *in[2] = {store, size};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Alloc, mode_T, 2, in);
+
+  res->attr.a.where = where;
+  res->attr.a.type = alloc_type;
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Free (ir_graph *irg, ir_node *block, ir_node *store,
+           ir_node *ptr, ir_node *size, type *free_type)
+{
+  ir_node *in[3] = {store, ptr, size};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_Free, mode_T, 3, in);
+
+  res->attr.f = free_type;
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_Sel (ir_graph *irg, ir_node *block, ir_node *store, ir_node *objptr,
+           int arity, ir_node **in, entity *ent)
+{
+  ir_node **r_in;
+  ir_node *res;
+  int r_arity;
+
+  r_arity = arity + 2;
+  NEW_ARR_A (ir_node *, r_in, r_arity);
+  r_in[0] = store;
+  r_in[1] = objptr;
+  memcpy (&r_in[2], in, sizeof (ir_node *) * arity);
+  res = new_ir_node (irg, block, op_Sel, mode_p, r_arity, r_in);
+
+  res->attr.s.ltyp = static_linkage;
+  res->attr.s.ent = ent;
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+inline ir_node *
+new_r_SymConst (ir_graph *irg, ir_node *block, type_or_id *value,
+                symconst_kind symkind)
+{
+  ir_node *in[0] = {};
+  ir_node *res;
+  res = new_ir_node (irg, block, op_SymConst, mode_I, 0, in);
+
+  res->attr.i.num = symkind;
+  if (symkind == linkage_ptr_info) {
+    res->attr.i.tori.ptrinfo = (ident *)value;
+  } else {
+    assert (   (   (symkind == type_tag)
+               || (symkind == size))
+            && (is_type(value)));
+    res->attr.i.tori.typ = (type *)value;
+  }
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+ir_node *
+new_r_Sync (ir_graph *irg, ir_node *block, int arity, ir_node **in)
+{
+  ir_node *res;
+
+  res = new_ir_node (irg, block, op_Sync, mode_M, arity, in);
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+
+ir_node *
+new_r_Bad (ir_node *block)
+{
+  return current_ir_graph->bad;
+}
+
+/***********************/
+/** public interfaces  */
+/** construction tools */
+
+ir_node *
+new_Start (void)
+{
+  ir_node *res;
+
+  res = new_ir_node (current_ir_graph, current_ir_graph->current_block,
+                    op_Start, mode_T, 0, NULL);
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+}
+
+
+ir_node *
+new_End (void)
+{
+  ir_node *res;
+
+  res = new_ir_node (current_ir_graph,  current_ir_graph->current_block,
+                    op_End, mode_X, -1, NULL);
+
+  res = optimize (res);
+  ir_vrfy (res);
+  return res;
+
+}
+
+ir_node *
+new_Block (void)
+{
+  ir_node *res;
+
+  res = new_ir_node (current_ir_graph, NULL, op_Block, mode_R, -1, NULL);
+  current_ir_graph->current_block = res;
+  res->attr.block.matured = 0;
+  set_Block_block_visit(res, 0);
+
+  // res = optimize (res); /* GL: only optimize if mature!!!! */
+  ir_vrfy (res);
+
+  /** create a new dynamic array, which stores all parameters in irnodes */
+  /** using the same obstack as the whole irgraph */
+  res->attr.block.graph_arr = NEW_ARR_D (ir_node *, current_ir_graph->obst,
+                                         current_ir_graph->params);
+
+  /** initialize the parameter array */
+  memset(res->attr.block.graph_arr, 0, sizeof(ir_node *)*current_ir_graph->params);
+
+  return res;
+}
+
+
+ir_node *
+new_Phi (int arity, ir_node **in, ir_mode *mode)
+{
+  return new_r_Phi (current_ir_graph, current_ir_graph->current_block,
+                   arity, in, mode);
+}
+
+ir_node *
+new_Const (ir_mode *mode, tarval *con)
+{
+  return new_r_Const (current_ir_graph, current_ir_graph->start_block,
+                     mode, con);
+}
+
+ir_node *
+new_Id (ir_node *val, ir_mode *mode)
+{
+  return new_r_Id (current_ir_graph, current_ir_graph->current_block,
+                  val, mode);
+}
+
+ir_node *
+new_Proj (ir_node *arg, ir_mode *mode, long proj)
+{
+  return new_r_Proj (current_ir_graph, current_ir_graph->current_block,
+                    arg, mode, proj);
+}
+
+ir_node *
+new_Conv (ir_node *op, ir_mode *mode)
+{
+  return new_r_Conv (current_ir_graph, current_ir_graph->current_block,
+                    op, mode);
+}
+
+ir_node *
+new_Tuple (int arity, ir_node **in)
+{
+  return new_r_Tuple (current_ir_graph, current_ir_graph->current_block,
+                     arity, in);
+}
+
+ir_node *
+new_Add (ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  return new_r_Add (current_ir_graph, current_ir_graph->current_block,
+                   op1, op2, mode);
+}
+
+ir_node *
+new_Sub (ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  return new_r_Sub (current_ir_graph, current_ir_graph->current_block,
+                   op1, op2, mode);
+}
+
+
+ir_node *
+new_Minus  (ir_node *op,  ir_mode *mode)
+{
+  return new_r_Minus (current_ir_graph, current_ir_graph->current_block,
+                     op, mode);
+}
+
+ir_node *
+new_Mul (ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  return new_r_Mul (current_ir_graph, current_ir_graph->current_block,
+                   op1, op2, mode);
+}
+
+ir_node *
+new_Quot (ir_node *memop, ir_node *op1, ir_node *op2)
+{
+  return new_r_Quot (current_ir_graph, current_ir_graph->current_block,
+                    memop, op1, op2);
+}
+
+ir_node *
+new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2)
+{
+  return new_r_DivMod (current_ir_graph, current_ir_graph->current_block,
+                      memop, op1, op2);
+}
+
+ir_node *
+new_Div (ir_node *memop, ir_node *op1, ir_node *op2)
+{
+  return new_r_Div (current_ir_graph, current_ir_graph->current_block,
+                   memop, op1, op2);
+}
+
+ir_node *
+new_Mod (ir_node *memop, ir_node *op1, ir_node *op2)
+{
+  return new_r_Mod (current_ir_graph, current_ir_graph->current_block,
+                   memop, op1, op2);
+}
+
+ir_node *
+new_And (ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  return new_r_And (current_ir_graph, current_ir_graph->current_block,
+                   op1, op2, mode);
+}
+
+ir_node *
+new_Or (ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  return new_r_Or (current_ir_graph, current_ir_graph->current_block,
+                  op1, op2, mode);
+}
+
+ir_node *
+new_Eor (ir_node *op1, ir_node *op2, ir_mode *mode)
+{
+  return new_r_Eor (current_ir_graph, current_ir_graph->current_block,
+                   op1, op2, mode);
+}
+
+ir_node *
+new_Not (ir_node *op, ir_mode *mode)
+{
+  return new_r_Not (current_ir_graph, current_ir_graph->current_block,
+                   op, mode);
+}
+
+ir_node *
+new_Shl (ir_node *op, ir_node *k, ir_mode *mode)
+{
+  return new_r_Shl (current_ir_graph, current_ir_graph->current_block,
+                   op, k, mode);
+}
+
+ir_node *
+new_Shr (ir_node *op, ir_node *k, ir_mode *mode)
+{
+  return new_r_Shr (current_ir_graph, current_ir_graph->current_block,
+                   op, k, mode);
+}
+
+ir_node *
+new_Shrs (ir_node *op, ir_node *k, ir_mode *mode)
+{
+  return new_r_Shrs (current_ir_graph, current_ir_graph->current_block,
+                    op, k, mode);
+}
+
+ir_node *
+new_Rotate (ir_node *op, ir_node *k, ir_mode *mode)
+{
+  return new_r_Rot (current_ir_graph, current_ir_graph->current_block,
+                    op, k, mode);
+}
+
+ir_node *
+new_Abs (ir_node *op, ir_mode *mode)
+{
+  return new_r_Abs (current_ir_graph, current_ir_graph->current_block,
+                   op, mode);
+}
+
+ir_node *
+new_Cmp (ir_node *op1, ir_node *op2)
+{
+  return new_r_Cmp (current_ir_graph, current_ir_graph->current_block,
+                   op1, op2);
+}
+
+ir_node *
+new_Jmp (void)
+{
+  return new_r_Jmp (current_ir_graph, current_ir_graph->current_block);
+}
+
+ir_node *
+new_Cond (ir_node *c)
+{
+  return new_r_Cond (current_ir_graph, current_ir_graph->current_block, c);
+}
+
+ir_node *
+new_Call (ir_node *store, ir_node *callee, int arity, ir_node **in,
+         type_method *type)
+{
+  return new_r_Call (current_ir_graph, current_ir_graph->current_block,
+                    store, callee, arity, in, type);
+}
+
+/* make M parameter in call explicit:
+new_Return (ir_node* store, int arity, ir_node **in) */
+ir_node *
+new_Return (ir_node* store, int arity, ir_node **in)
+{
+  return new_r_Return (current_ir_graph, current_ir_graph->current_block,
+                      store, arity, in);
+}
+
+ir_node *
+new_Raise (ir_node *store, ir_node *obj)
+{
+  return new_r_Raise (current_ir_graph, current_ir_graph->current_block,
+                     store, obj);
+}
+
+ir_node *
+new_Load (ir_node *store, ir_node *addr)
+{
+  return new_r_Load (current_ir_graph, current_ir_graph->current_block,
+                    store, addr);
+}
+
+ir_node *
+new_Store (ir_node *store, ir_node *addr, ir_node *val)
+{
+  return new_r_Store (current_ir_graph, current_ir_graph->current_block,
+                     store, addr, val);
+}
+
+ir_node *
+new_Alloc (ir_node *store, ir_node *size, type *alloc_type,
+           where_alloc where)
+{
+  return new_r_Alloc (current_ir_graph, current_ir_graph->current_block,
+                     store, size, alloc_type, where);
+}
+
+ir_node *
+new_Free (ir_node *store, ir_node *ptr, ir_node *size, type *free_type)
+{
+  return new_r_Free (current_ir_graph, current_ir_graph->current_block,
+                    store, ptr, size, free_type);
+}
+
+ir_node *
+new_simpleSel (ir_node *store, ir_node *objptr, entity *ent)
+/* GL: objptr was called frame before.  Frame was a bad choice for the name
+   as the operand could as well be a pointer to a dynamic object. */
+{
+  return new_r_Sel (current_ir_graph, current_ir_graph->current_block,
+                   store, objptr, 0, NULL, ent);
+}
+
+ir_node *
+new_Sel (ir_node *store, ir_node *objptr, int n_index, ir_node **index, entity *sel)
+{
+  return new_r_Sel (current_ir_graph, current_ir_graph->current_block,
+                   store, objptr, n_index, index, sel);
+}
+
+ir_node *
+new_SymConst (type_or_id *value, symconst_kind kind)
+{
+  return new_r_SymConst (current_ir_graph, current_ir_graph->current_block,
+                         value, kind);
+}
+
+ir_node *
+new_Sync (int arity, ir_node** in)
+{
+  return new_r_Sync (current_ir_graph, current_ir_graph->current_block,
+                    arity, in);
+}
+
+
+ir_node *
+new_Bad (void)
+{
+  return current_ir_graph->bad;
+}
+
+#if 0
+/************************/
+/* ir block constructor */
+
+/* GL: what's this good for? */
+
+typedef struct ir_block {
+  char closed;
+  char matured;
+  /* -1 = error, 0 = OK */
+} ir_block;
+
+ir_block *
+new_ir_Block(void)
+{
+  ir_block *res;
+
+  res->closed = -1;
+  res->matured = -1;
+
+  return res;
+}
+#endif
+
+/* initialize */
+
+/* call once for each run of the library */
+void
+init_cons (void)
+{
+}
diff --git a/ir/ir/ircons.h b/ir/ir/ircons.h
new file mode 100644 (file)
index 0000000..bab9e6b
--- /dev/null
@@ -0,0 +1,1084 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer,
+**          Goetz Lindenmaier
+**
+** ircons.h ir node construction
+*/
+
+
+/** !!!
+*** Ideas for improvement:
+***
+ Handle construction of exceptions more comfortable:
+ Add new constructors that pass the exception region (or better the
+ Phi for the memories, the ex. region can be found from there) as parameter,
+ constructor then adds all Proj nodes and returns the pointer
+ to the Proj node that selects the result of the arithmetic operation.
+
+ Maybe hide the exception region in a global variable, especially if
+ it is always unambiguous.
+**/
+
+
+/**
+***  IRCONS
+
+  This file documents all datatypes and constructors needed to
+  build a FIRM representation of a pocedure.  The constructors are
+  also implemented in this file.
+
+  The documentation also gives a short manual how to use the library.
+
+  For extensive documentation of FIRM see UKA Techreport 1999-14.
+
+  DATATYPES
+  =========
+
+  The struct ir_graph
+  -------------------
+
+    This struct contains all information about a procedure.
+    It's allocated directly to memory.
+
+    The fields of ir_graph:
+
+    *ent             The entity describing this procedure.
+
+    The beginning and end of a graph:
+
+    *start_block     This ir_node is the block that contains the unique
+                     start node of the procedure.  With it it contains
+                     the Proj's on starts results.
+                     Further all Const nodes are placed in the start block.
+    *start           This ir_node is the unique start node of the procedure.
+
+    *end_block       This ir_node is the block that contains the unique
+                     end node of the procedure.  This block contains no
+                     further nodes.
+    *end             This ir_node is the unique end node of the procedure.
+
+    The following nodes are Projs from the start node, held in ir_graph for
+    simple access:
+
+    *frame           The ir_node producing the pointer to the stack frame of the
+                     procedure as output.  This is the Proj node on the third
+                     output of the start node.  This output of the start node
+                     is tagged as pns_frame_base.  In FIRM most lokal
+                     variables are modeled as data flow edges.  Static
+                     allocated arrays can not be represented as dataflow
+                     edges. Therefore FIRM has to represent them in the stack
+                     frame.
+
+    *globals         This models a pointer to a  space in the memory where _all_
+                    global things are held.  Select from this pointer with a Sel
+                    node the pointer to a global variable / procedure / compiler
+                    known function... .
+
+    *args            The ir_node that produces the arguments of the method as it's
+                     result.  This is a Proj node on the fourth output of the start
+                     node.  This output is tagged as pns_args.
+
+    *bad             The bad node is an auxiliary node. It is needed only once,
+                     so there is this globally reachable node.
+
+    Datastructures that are private to a graph:
+
+    *obst            An obstack that contains all nodes.
+
+    *current_block   A pointer to the current block.  Any node created with one
+                     of the node constructors (new_<opcode>) are assigned to this
+                     block.  It can be set with switch_block(block).  Only needed
+                    for ir construction.
+
+    params/n_loc     An int giving the number of local variables in this procedure.
+                    This is neede for ir construction. Name will be changed.
+
+    *value_table     This pset is used for global value numbering for optimizing
+                     use in iropt.c.
+
+    *Phi_in_stack;   a stack needed for automatic Phi construction, needed only
+                    during ir construction.
+
+
+  Three kinds of nodes
+  --------------------
+
+    There are three kinds of nodes known to the ir:  enties,
+    types, and ir_nodes
+
+    + ir_nodes are the actual nodes of the FIRM intermediate representation.
+      They represent operations on the data of the program and control flow
+      operations.
+
+    + entity ==> implemented in entity.h
+      Refers to a single entity of the compiled program, e.g. a field of a class or
+      a method.
+
+    + types ==> implemented in type.h
+      With types type information is represented.  There are several type nodes.
+
+  Implementation of the FIRM operations: ir_node
+  ----------------------------------------------
+
+    Ir_nodes represent operations on the data of the program and control flow
+    operations.  Examples of ir_nodes:  Add, Jmp, Cmp
+
+    FIRM is a dataflow graph.  A dataflow graph is a directed graph,
+    so that every node has incoming and outgoing edges.  A node is
+    executable if every input at it's incoming edges is available.
+    Execution of the dataflow graph is started at the Start node which
+    has no incoming edges and ends when the End node executes, even if
+    there are still executable or not executed nodes.  (Is this true,
+    or must all executable nodes be executed?)  (There are exceptions
+    to the dataflow paradigma that all inputs have to be available
+    before a node can execute: Phi, Block.  See UKA Techreport
+    1999-14.)
+
+    The implementation of FIRM differs from the view as a dataflow
+    graph.  To allow fast traversion of the graph edges are
+    implemented as C-pointers.  Inputs to nodes are not ambiguous, the
+    results can be used by several other nodes.  Each input can be
+    implemented as a single pointer to a predecessor node, outputs
+    need to be lists of pointers to successors.  Therefore a node
+    contains pointers to it's predecessor so that the implementation is a
+    dataflow graph with reversed edges.  It has to be traversed bottom
+    up.
+
+    All nodes of the ir have the same basic structure.  They are
+    distinguished by a field containing the opcode.
+
+    The fields of an ir_node:
+
+    kind             A firm_kind tag containing k_ir_node.  This is useful for
+                     dynamically checking the type of a node.
+
+    *op              This ir_op gives the opcode as a tag and a string
+                     and the number of attributes of an ir_node.  There is
+                     one statically allocated struct ir_op for each opcode.
+
+    *mode            The ir_mode of the operation represented by this firm node.
+                     The mode of the operation is the mode of it's result.  A Firm
+                     mode is a datatype as known to the target, not a type of the
+                     source language.
+
+    visit            A flag for traversing the ir.
+
+    **in             An array with pointers to the node's predecessors.
+
+    *link            A pointer to an ir_node.  With this pointer all Phi nodes
+                     are attached to a Block, i.e., a Block points to it's
+                     first Phi node, this node points to the second Phi node
+                     in the Block and so fourth.  Used in mature_block
+                     to find all Phi nodes to be matured.  It's also used to
+                    annotate a node with a better, optimized version of it.
+
+    attr             An attr struct containing the attributes of the nodes. The
+                     attributes depend on the opcode of the node.  The number of
+                     these attributes is given in op.
+
+  The struct ir_op
+  ----------------
+                     Not yet documented. See irop.h.
+
+  The struct ir_mode
+  ------------------
+                     Not yet documented. See irmode.h.
+
+  GLOBAL VARIABLES
+  ================
+
+  current_ir_graph   Points to the current ir_graph.  All constructors for nodes
+                     add nodes to this graph.
+
+  ir_visited         A int used as flag to traverse the ir_graph.
+
+  block_visited      A int used as a flag to traverse block nodes in the graph.
+
+                     Others not yet documented.
+
+
+
+
+  CONSTRUCTOR FOR IR_GRAPH
+  ========================
+
+  ir_graph *new_ir_graph (entity *ent, int params);
+  -------------------------------------------------
+
+  This constructor generates the basic infrastructure needed to
+  represent a procedure in FIRM.
+
+  The parameters of new_ir_graph are:
+
+    *ent             A pointer to an entity representing the procedure.
+
+    params           An integer giving the number of local variables in the
+                     procedure.
+
+  It allocates an ir_graph and sets current_ir_graph to point to this
+  graph.  Further it allocates the following nodes needed for every
+  procedure:
+
+  * The start block containing a start node and Proj nodes for it's
+    four results (X, M, P, T).
+  * The end block containing an end node. This block is not matured
+    after executing new_ir_graph as predecessors need to be added to it.
+    (Maturing a block means fixing it's number of predecessors.)
+  * The current block, which is empty and also not matured.
+
+  Further it enters the global store into the datastructure of the start
+  block that contanis all valid values in this block (set_store()).  This
+  datastructure is used to build the Phi nodes and removed after completion
+  of the graph.
+  There is no path from end to start in the graph after calling ir_graph.
+
+
+  IR_NODES AND CONSTRUCTORS FOR IR_NODES
+  =======================================
+
+  All ir_nodes are defined by a common data structure.  They are distinguished
+  by their opcode and differ in the number of their attributes.
+
+  The constructor for the block node sets current_block to itself.
+  Const nodes are always added to the start block.
+  All other constructors add the created node to the current_block.
+  swich_block(block) allows to set the current block to block.
+
+  Watch for my inconsistent use of input and predecessor (dataflow view)
+  and `the node points to' (implementation view).
+
+  The following description of the nodes lists four properties them if these are
+  of interest:
+   - the parameters to the constructor
+   - the inputs of the Firm node
+   - the outputs of the Firm node
+   - attributes to the node
+
+
+  BASIC BLOCKS
+  ------------
+
+  ir_node *new_Block (void)
+  --------------------------
+
+  Creates a new block.  Sets current_block to itself.  When a new block is
+  created it cannot be known how many predecessors this block will have in the
+  control flow graph. Therefore the list of inputs can not be fixed at
+  creation.  Predecessors can be added with add_in_edge (block, control flow
+  operation).  With every added predecessor the number of inputs to Phi nodes
+  also changes.
+
+  The block can be completed by mature_block(block) if all predecessors are
+  known.  If several blocks are built at once, mature_block can only be called
+  after set_value has been called for all values that are life at the end
+  of the block.  This is necessary so that Phi nodes created by mature_block
+  get the right predecessors in case of cyclic dependencies.  If all set_values
+  of this block are called after maturing it and before calling get_value
+  in some block that is control flow dependent on this block, the construction
+  is correct.
+  Example for faulty ir construction:
+    block_before_loop = new_block();
+    set_value(x);
+    mature_block(block_before_loop);
+    before2header = new_Jmp;
+
+    loop_header = new_block ();
+    header2body - new_Jmp();
+
+    loop_body = new_block ();
+    body2header = new_Jmp();
+
+    add_in_edge(loop_header, before2header);
+    add_in_edge(loop_header, body2header);
+    add_in_edge(loop_body, header2body);
+
+    mature_block(loop_header);
+    mature_block(loop_body);
+
+    get_value(loop_body, x);   // gets the Phi in loop_header
+    set_value(loop_header, x); // sets the value the above get_value should
+                               // have returned!!!
+  Mature_block also fixes the number of inputs to the Phi nodes.  Mature_block
+  should be called as early as possible, as afterwards the generation of Phi
+  nodes is more efficient.
+
+  Inputs:
+    There is an input for each control flow predecessor of the block.
+    The input points to an instruction producing an output of type X.
+    Possible predecessors:  Start, Jmp, Cond, Raise or Return or any node
+    possibly causing an exception.  (Often the real predecessors are Projs.)
+  Output:
+    Mode R, all nodes belonging to this block should consume this output.
+    As they are strict (except Block and Phi node) it is a necessary condition
+    that the block node executed before any other node in this block
+    executes.
+  Attributes:
+    block.matured  Indicates whether the block is mature.
+    block.closed   ???
+    block.**graph_arr
+                    This attribute contains all local values valid in this
+                    block. This is needed to build the Phi nodes and removed
+                    if the graph is complete.
+
+
+  CONTROL FLOW OPERATIONS
+  -----------------------
+
+  In each block there must be exactly one of the control flow
+  operations Start, End, Jmp, Cond, Return or Raise.  The output of a
+  control flow operation points to the block to be executed next.
+
+  ir_node *new_Start (void)
+  -------------------------
+
+  Creates a start node.  Not actually needed public.  Created
+  by new_ir_graph.
+
+  Inputs:
+    No inputs except the block it belogns to.
+  Output:
+    A tuple of 4 (5, 6) distinct values. These are labeled by the following
+    projection numbers (pns_number):
+    * pns_initial_exec
+                     mode X, points to the first block to be executed.
+    * pns_global_store
+                     mode M, the global store
+    * pns_frame_base mode P, a pointer to the base of the procedures stack frame.
+    * pns_globals    mode P, a pointer to the part of the memory containing _all_
+                             global things.
+    * pns_args       mode T, a tuple containing all arguments of the procedure.
+
+
+  ir_node *new_End (void)
+  -----------------------
+
+  Creates an end node.  Not actually needed public.  Created by
+  new_ir_graph.
+
+  Inputs:
+    No inputs except the block it belogns to.
+  Output:
+    No output.
+
+  ir_node *new_Jmp (void)
+  -----------------------
+
+  Creates a Jmp node.
+
+  Inputs:
+    The block the node belongs to
+  Output:
+    Control flow to the next block.
+
+  ir_node *new_Cond (ir_node *c)
+  ------------------------------
+
+  Creates a Cond node.  There are two versions of this node.
+
+  The Boolean Cond:
+  Input:
+    A value of mode b.
+  Output:
+    A tuple of two control flows.  The first is taken if the input is
+    false, the second if it is true.
+
+  The Switch Cond:
+  Input:
+    A value of mode I_u. (i)
+  Output:
+    A tuple of n control flows.  If the Cond's input is i, control
+    flow will procede along output i. If the input is >= n control
+    flow proceeds along output n.
+
+  ir_node *new_Return (in_node *store, int arity, ir_node **in)
+  -------------------------------------------------------------
+
+  The return node has as inputs the results of the procedure.  It
+  passes the control flow to the end_block.
+
+  Inputs:
+    The memory state.
+    All results.
+  Output
+    Control flow to the end block.
+
+  ir_node *new_Raise (ir_node *store, ir_node *obj)
+  -------------------------------------------------
+
+  Raises an exception.  Unconditional change of control flow.  Writes
+  an explicit Except variable to memory to pass it to the exception
+  handler.  See TechReport 1999-14, chapter Exceptions.
+
+  Inputs:
+    The memory state.
+    A pointer to the Except variable.
+  Output:
+    A tuple of control flow and the changed memory state.  The control flow
+    points to the exception handler if it is definied in this procedure,
+    else it points to the end_block.
+
+
+  CONSTANTS
+  ---------
+
+  ir_node *new_Const (ir_mode *mode, tarval *con)
+  -----------------------------------------------
+
+  Creates a constant in the constant table and adds a Const node
+  returning this value to the start block.
+
+  Parameters:
+    *mode            The mode of the constant.
+    *con             Points to an entry in the constant table.
+                     This pointer is added to the attributes of
+                     the node (self->attr.con)
+  Inputs:
+    No inputs except the block it belogns to.
+  Output:
+    The constant value.
+  Attribute:
+    attr.con   A tarval* pointer to the proper entry in the constant
+               table.
+
+  ir_node *new_SymConst (type *type, symconst_kind kind)
+  ------------------------------------------------------------
+
+  There are two kinds of symbolic constants:
+    type_tag  The symbolic constant represents a type tag.
+    size      The symbolic constant represents the size of a class.
+    link_info Information for the linker.
+
+  Parameters
+    kind       The kind of the symbolic constant: type_tag or size.
+    *type      Points to the type the tag stands for or to the type
+               whose size is represented by the constant.
+
+  Inputs:
+    No inputs except the block it belogns to.
+  Output:
+    An unsigned integer (I_u) or a pointer (P).
+
+  Attributes:
+    attr.i.num       The symconst_kind, i.e. one of
+                      - type_tag
+                      - size
+                     - linkage_ptr_info
+      If the attr.i.num is type_tag of size, the node contains an attribute
+    attr.i.*type     A pointer to a type_class.
+      if it is linkage_ptr_info it contains
+    attr.i.*ptrinfo  A ident holding information for the linker.
+
+  THE SELECT NODE
+  ---------------
+
+  ir_node *new_simpleSel (ir_node *store, ir_node *frame, entity *sel)
+  --------------------------------------------------------------------
+
+
+  Selects an entity from a compound type. This entity can be a field or
+  a method.
+
+  Parameters:
+    *store     The memory in which the object the entity should be selected from
+               is allocated.
+    *frame     The pointer to the object.
+    *sel       The entity to select.
+
+  Inputs:
+    The memory containing the object.
+    A pointer to the object.
+    An unsigned integer.
+  Output:
+    A pointer to the selected entity.
+  Attributes:
+    attr.sel   Pointer to the entity
+
+
+  ir_node *new_Sel (ir_node *store, ir_node *frame, int arity, ir_node **in,
+  --------------------------------------------------------------------------
+                    entity *sel)
+                    ------------
+
+  Selects a field from an array type.  The entity has as owner the array, as
+  type the arrays element type.  The indexes to access an array element are
+  given also.
+
+  Parameters:
+    *store     The memory in which the object the entity should be selected from
+               is allocated.
+    *frame     The pointer to the object.
+    *arity     number of array indexes.
+    *in        array with index inputs to the node.
+    *sel       The entity to select.
+
+  Inputs:
+    The memory containing the object.
+    A pointer to the object.
+    As much unsigned integer as there are array expressions.
+  Output:
+    A pointer to the selected entity.
+  Attributes:
+    attr.sel   Pointer to the entity
+
+  The constructors new_Sel and new_simpleSel generate the same ir nodes.
+  simpleSel just sets the arity of the index inputs to zero.
+
+
+  ARITHMETIC OPERATIONS
+  ---------------------
+
+  ir_node *new_Call (ir_node *store, ir_node *callee, int arity, ir_node **in,
+  ----------------------------------------------------------------------------
+                     type_method *type)
+                     ------------------
+
+  Creates a procedure call.
+
+  Parameters
+    *store           The actual store.  Why not also the stack frame?
+    *callee          A pointer to the called procedure.
+    arity            The number of procedure parameters.
+    **in             An array with the pointers to the parameters.
+                     This array is copied in the constructor.
+    *type            Type information of the procedure called.
+
+  Inputs:
+    The store, the callee and the parameters.
+  Output:
+    A tuple containing the eventually changed store and the procedure
+    results.
+  Attributes:
+    attr.call        Contains the type information for the procedure.
+
+  ir_node *new_Add (ir_node *op1, ir_node *op2, ir_mode *mode)
+  ------------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Sub (ir_node *op1, ir_node *op2, ir_mode *mode)
+  ------------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Minus (ir_node *op, ir_mode *mode)
+  -----------------------------------------------
+
+  This constructor is for unary Minus operations on floating point
+  values.  Such a Minus can trap if it is implemented as a Sub from
+  zero due to rounding errors.
+
+  ir_node *new_Mul (ir_node *op1, ir_node *op2, ir_mode *mode)
+  ------------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Quot (ir_node *memop, ir_node *op1, ir_node *op2)
+  --------------------------------------------------------------
+
+  Quot performs exact division of floating point numbers.  It's mode
+  is Tuple, the mode of the result must be annotated to the Proj
+  that extracts the result of the arithmetic operations.
+
+  Inputs:
+    The store needed to model exceptions and the two operands.
+  Output:
+    A tuple contaning a memory and a execution for modeling exceptions
+    and the result of the arithmetic operation.
+
+  ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2)
+  ----------------------------------------------------------------
+
+  Performs Div and Mod on interger values.
+
+  Output:
+    A tuple contaning a memory and a execution for modeling exceptions
+    and the two result of the arithmetic operations.
+
+  ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2)
+  -------------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Mod (ir_node *memop, ir_node *op1, ir_node *op2)
+  -------------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Abs (ir_node *op, ir_mode *mode)
+  ---------------------------------------------
+
+  Trivial.
+
+  ir_node *new_And (ir_node *op1, ir_node *op2, ir_mode *mode)
+  ------------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Or (ir_node *op1, ir_node *op2, ir_mode *mode)
+  -----------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Eor (ir_node *op1, ir_node *op2, ir_mode *mode)
+  ------------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Not (ir_node *op, ir_mode *mode)
+  ---------------------------------------------
+
+  This node constructs a constant where all bits are set to one
+  and a Eor of this constant and the operator.  This simulates a
+  Not operation.
+
+  ir_node *new_Shl (ir_node *op, ir_node *k, ir_mode *mode)
+  ---------------------------------------------------------
+
+  Trivial.
+
+  ir_node *new_Shr (ir_node *op, ir_node *k, ir_mode *mode)
+  ---------------------------------------------------------
+
+  Logic shift right, i.e., zero extended.
+
+
+  ir_node *new_Shrs (ir_node *op, ir_node *k, ir_mode *mode)
+  ----------------------------------------------------------
+
+  Arithmetic shift right, i.e., sign extended.
+
+  ir_node *new_Rot (ir_node *op, ir_node *k, ir_mode *mode)
+  ---------------------------------------------------------
+
+  Rotates the operand to the (right??) by k bits.
+
+  ir_node *new_Conv (ir_node *op, ir_mode *mode)
+  ---------------------------------------------
+
+  Mode conversion.  For allowed conversions see UKA Tech Report
+  1999-14.
+
+  ir_node *new_Cmp (ir_node *op1, ir_node *op2)
+  ---------------------------------------------
+
+  Input:
+    The two values to be compared.
+  Output:
+    A 16-tuple containing the results of the 16 different comparisons.
+    The following is a list giving the comparisons and a projection
+    number (pnc_number) to use in Proj nodes to extract the proper result.
+      False     false
+      Eq        equal
+      Lt       less
+      Le       less or equal
+      Gt       greater
+      Ge       greater of equal
+      Lg       less or greater
+      Leg      less, equal or greater = ordered
+      Uo       unordered
+      Ue       unordered or equal
+      Ul       unordered or less
+      Ule      unordered, less or equal
+      Ug       unordered or greater
+      Uge      unordered, greater or equal
+      Ne       unordered, less or greater = not equal
+      True     true
+
+
+
+  THE PHI NODE
+  ------------
+
+  In general, Phi nodes are automaitcally inserted.  In some cases, if
+  all predecessors of a block are known, an explicit Phi node constructor
+  is needed.  E.g., to construct a FIRM graph for a statement as
+    a = (b==c) ? 2 : 5;
+
+  ir_node *new_Phi (int arity, ir_node **in, ir_mode *mode)
+  ---------------------------------------------------------
+
+  Creates a Phi node. The in's order has to correspond to the order
+  of in's of current_block.  This is not checked by the library!
+
+  Parameter
+    arity            number of predecessors
+    **in             array with predecessors
+    *mode            The mode of it's inputs and output.
+  Inputs:
+    A Phi node has as many inputs as the block it belongs to.
+    Each input points to a definition of the same value on a
+    different path in the control flow.
+  Output
+    The definition valid in this block.
+
+
+  OPERATIONS TO MANAGE MEMORY EXPLICITLY
+  --------------------------------------
+
+  ir_node *new_Load (ir_node *store, ir_node *addr)
+  ----------------------------------------------------------------
+
+  The Load operation reads a value from memory.
+
+  Parameters:
+  *store        The current memory.
+  *addr         A pointer to the variable to be read in this memory.
+  *mode         The mode of the loaded value.
+
+  Inputs:
+    The memory and a pointer to a variable in this memory.
+  Output:
+    A tuple of the memory, a control flow to be taken in case of
+    an exception and the loaded value.
+
+  ir_node *new_Store (ir_node *store, ir_node *addr, ir_node *val)
+  ----------------------------------------------------------------
+
+  The Store operation writes a value to a variable in memory.
+
+  Inputs:
+    The memory, a pointer to a variable in this memory and the value
+    to write to this variable.
+  Output:
+    A tuple of the changed memory and a control flow to be taken in
+    case of an exception.
+
+  ir_node *new_Alloc (ir_node *store, ir_node *size, type *alloc_type,
+  --------------------------------------------------------------------
+                      where_alloc where)
+                      ------------------
+
+  The Alloc node allocates a new variable.  It can be specified whether the
+  variable should be allocated to the stack or to the heap.
+
+  Parameters:
+    *store       The memory which shall contain the new variable.
+    **    *size        The number of bytes to allocate. Old. **
+    *size        We decided that the size easily can be derived from the type.
+                 This field is for allocating arrays, i.e., it gives the multiple
+                of the size of alloc_type to allocate memory for.
+    *alloc_type  The type of the allocated variable.
+    where        Where to allocate the variable, either heap_alloc or stack_alloc.
+
+  Inputs:
+    A memory and an unsigned integer.
+  Output:
+    A tuple of the changed memory, a control flow to be taken in
+    case of an exception and the pointer to the new variable.
+  Attributes:
+    a.where          Indicates where the variable is allocated.
+    a.*type          A pointer to the class the allocated data object
+                     belongs to.
+
+  ir_node *new_Free (ir_node *store, ir_node *ptr, type *free_type)
+  ------------------------------------------------------------------
+
+  The Free node frees memory of the given variable.
+
+  Parameters:
+    *store       The memory which shall contain the new variable.
+    *ptr         The pointer to the object to free.
+    *size        The number of objects of type free_type to free in a sequence.
+    *free_type   The type of the freed variable.
+
+  Inputs:
+    A memory, a pointer and an unsigned integer.
+  Output:
+    The changed memory.
+  Attributes:
+    f.*type          A pointer to the type information of the freed data object.
+
+  Not Implemented!
+
+  ir_node *new_Sync (int arity, ir_node **in)
+  -------------------------------------------
+
+  The Sync operation unifies several partial memory blocks.  These blocks
+  have to be pairwise disjunct or the values in common locations have to
+  be identical.  This operation allows to specify all operations that eventually
+  need several partial memory blocks as input with a single entrance by
+  unifying the memories with a preceding Sync operation.
+
+  Parameters
+    arity    The number of memories to syncronize.
+    **in     An array of pointers to nodes that produce an output of
+             type memory.
+  Inputs
+    Several memories.
+  Output
+    The unified memory.
+
+
+  SPECIAL OPERATIONS
+  ------------------
+
+  ir_node *new_Bad (void)
+  -----------------------
+
+  Returns the unique Bad node current_ir_graph->bad.
+  This node is used to express results of dead code elimination.
+
+  ir_node *new_Proj (ir_node *arg, ir_mode *mode, long proj)
+  ----------------------------------------------------------
+
+  Selects one entry of a tuple.  This is a hidden `fat edge'.
+
+  Parameters
+    *arg      A node producing a tuple.
+    *mode     The mode of the value to project.
+    proj      The position of the value in the tuple.
+  Input:
+    The tuple.
+  Output:
+    The value.
+
+  ir_node *new_Tuple (int arity, ir_node **in)
+  --------------------------------------------
+
+  Builds a Tuple from single values.  This is needed to implement
+  optimizations that remove a node that produced a tuple.  The node can be
+  replaced by the Tuple operation so that the following Proj nodes have not to
+  be changed.  (They are hard to find due to the implementation with pointers
+  in only one direction.)  The Tuple node is smaller than any other
+  node, so that a node can be changed into a Tuple by just changing it's
+  opcode and giving it a new in array.
+
+  Parameters
+    arity    The number of tuple elements.
+    **in     An array containing pointers to the nodes producing the
+             tuple elements.
+
+  ir_node *new_Id (ir_node *val, ir_mode *mode)
+  ---------------------------------------------
+
+  The single output of the Id operation is it's input.  Also needed
+  for optimizations.
+
+
+  COPING WITH DATA OBJECTS
+  ========================
+
+  Two kinds of data objects have to be distinguished for generating
+  FIRM.  First there are local variables other than arrays that are
+  known to be alias free.  Second there are all other data objects.
+  For the first a common SSA representation is built, the second
+  are modeled by saving them to memory.  The memory is treated as
+  a single local variable, the alias problem is hidden in the
+  content of this variable.
+
+  All values known in a Block are listed in the block's attribute,
+  block.**graph_arr which is used to automatically insert Phi nodes.
+  The following two funcions can be used to add a newly computed value
+  to the array, or to get the producer of a value, i.e., the current
+  live value.
+
+  inline void set_value (int pos, ir_node *value)
+  -----------------------------------------------
+
+  Has to be called for every assignment to a local variable.  It
+  adds the value to the array of used values at position pos.  Pos
+  has to be a unique identifier for an entry in the procedure's
+  definition table.  It can be used to access the value again.
+
+  ir_node *get_value (int pos, ir_mode *mode)
+  -------------------------------------------
+
+  Returns the node defining the value referred to by pos. If the
+  value is not defined in this block a Phi node is generated and
+  all definitions reaching this Phi node are collected.  It can
+  happen that the algorithm allocates an unnecessary Phi node,
+  e.g. if there is only one definition of this value, but this
+  definition reaches the currend block on several different
+  paths.  This Phi node will be eliminated if optimizations are
+  turned on right after it's creation.
+
+
+  There are two special routines for the global store:
+
+  inline void set_store (ir_node *store)
+  --------------------------------------
+
+  Adds the store to the array of known values at a reserved
+  position.
+
+  inline ir_node *get_store (void)
+  --------------------------------
+
+  Returns the node defining the actual store.
+
+**/
+
+
+# ifndef _IRCONS_H_
+# define _IRCONS_H_
+
+# include "irgmod.h"
+# include "irmode.h"
+# include "entity.h"
+# include "tv.h"
+# include "common.h"
+# include "irop.h"
+# include "irgraph.h"
+# include "type.h"
+# include "pdeq.h"
+# include "irvrfy.h"
+
+/* irnode constructor                                             */
+/* Create a new irnode in irg, with an op, mode, arity and        */
+/* some incoming irnodes.                                         */
+/* If arity is negative, a node with a dynamic array is created.  */
+inline ir_node *new_ir_node (ir_graph *irg, ir_node *block, ir_op *op,
+                            ir_mode *mode, int arity, ir_node **in);
+
+/** These headers need not to be here. They are never used by the
+    public.
+    That's not completely true.  They need not be seen by a frontend,
+    but they might be useful for optimizations changing the IR. **/
+
+#if USE_EXPICIT_PHI_IN_STACK
+/* A stack needed for the automatic Phi node construction in constructor
+   Phi_in. */
+typedef struct Phi_in_stack {
+  ir_node **stack;
+  int       pos;
+} Phi_in_stack;
+#endif
+
+/* privat interfaces */
+/* more detailed construction */
+
+ir_node *new_r_Jmp    (ir_graph *irg, ir_node *block);
+ir_node *new_r_Cond   (ir_graph *irg, ir_node *block, ir_node *c);
+ir_node *new_r_Return (ir_graph *irg, ir_node *block,
+                      ir_node *store, int arity, ir_node **in);
+ir_node *new_r_Raise  (ir_graph *irg, ir_node *block,
+                      ir_node *store, ir_node *obj);
+ir_node *new_r_Const  (ir_graph *irg, ir_node *block,
+                      ir_mode *mode, tarval *con);
+ir_node *new_r_SymConst (ir_graph *irg, ir_node *block,
+                       type_or_id *value, symconst_kind symkind);
+ir_node *new_r_Sel    (ir_graph *irg, ir_node *block, ir_node *store,
+                       ir_node *objptr, int n_index, ir_node **index,
+                      entity *ent);
+ir_node *new_r_Call   (ir_graph *irg, ir_node *block, ir_node *store,
+                      ir_node *callee, int arity, ir_node **in, type_method *type);
+ir_node *new_r_Add    (ir_graph *irg, ir_node *block,
+                      ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_r_Sub    (ir_graph *irg, ir_node *block,
+                      ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_r_Minus  (ir_graph *irg, ir_node *block,
+                      ir_node *op,  ir_mode *mode);
+ir_node *new_r_Mul    (ir_graph *irg, ir_node *block,
+                      ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_r_Quot   (ir_graph *irg, ir_node *block, ir_node *memop,
+                      ir_node *op1, ir_node *op2);
+ir_node *new_r_DivMod (ir_graph *irg, ir_node *block,
+                      ir_node *memop, ir_node *op1, ir_node *op2);
+ir_node *new_r_Div    (ir_graph *irg, ir_node *block, ir_node *memop,
+                      ir_node *op1, ir_node *op2);
+ir_node *new_r_Mod    (ir_graph *irg, ir_node *block, ir_node *memop,
+                      ir_node *op1, ir_node *op2);
+ir_node *new_r_Abs    (ir_graph *irg, ir_node *block,
+                       ir_node *op, ir_mode *mode);
+ir_node *new_r_And    (ir_graph *irg, ir_node *block,
+                      ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_r_Or     (ir_graph *irg, ir_node *block,
+                      ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_r_Eor    (ir_graph *irg, ir_node *block,
+                      ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_r_Not    (ir_graph *irg, ir_node *block,
+                      ir_node *op, ir_mode *mode);
+ir_node *new_r_Shl    (ir_graph *irg, ir_node *block,
+                      ir_node *op, ir_node *k, ir_mode *mode);
+ir_node *new_r_Shr    (ir_graph *irg, ir_node *block,
+                      ir_node *op, ir_node *k, ir_mode *mode);
+ir_node *new_r_Shrs   (ir_graph *irg, ir_node *block,
+                      ir_node *op, ir_node *k, ir_mode *mode);
+ir_node *new_r_Rot    (ir_graph *irg, ir_node *block,
+                      ir_node *op, ir_node *k, ir_mode *mode);
+ir_node *new_r_Cmp    (ir_graph *irg, ir_node *block,
+                      ir_node *op1, ir_node *op2);
+ir_node *new_r_Conv   (ir_graph *irg, ir_node *block,
+                      ir_node *op, ir_mode *mode);
+ir_node *new_r_Phi    (ir_graph *irg, ir_node *block, int arity,
+                      ir_node **in, ir_mode *mode);
+ir_node *new_r_Load   (ir_graph *irg, ir_node *block,
+                      ir_node *store, ir_node *adr);
+ir_node *new_r_Store  (ir_graph *irg, ir_node *block,
+                      ir_node *store, ir_node *adr, ir_node *val);
+ir_node *new_r_Alloc  (ir_graph *irg, ir_node *block, ir_node *store,
+                      ir_node *size, type *alloc_type, where_alloc where);
+ir_node *new_r_Free   (ir_graph *irg, ir_node *block, ir_node *store,
+                      ir_node *ptr, ir_node *size, type *free_type);
+ir_node *new_r_Sync   (ir_graph *irg, ir_node *block, int arity, ir_node **in);
+ir_node *new_r_Proj   (ir_graph *irg, ir_node *block, ir_node *arg,
+                      ir_mode *mode, long proj);
+ir_node *new_r_Tuple  (ir_graph *irg, ir_node *block,
+                      int arity, ir_node **in);
+ir_node *new_r_Id  (ir_graph *irg, ir_node *block,
+                   ir_node *val, ir_mode *mode);
+ir_node *new_r_Bad (ir_node *block);
+
+
+
+/* public interfaces */
+/* normal constructors */
+
+ir_node *new_Block  (void);
+ir_node *new_Start  (void);
+ir_node *new_End    (void);
+ir_node *new_Jmp    (void);
+ir_node *new_Cond   (ir_node *c);
+ir_node *new_Return (ir_node *store, int arity, ir_node **in);
+ir_node *new_Raise  (ir_node *store, ir_node *obj);
+ir_node *new_Const  (ir_mode *mode, tarval *con);
+ir_node *new_SymConst (type_or_id *value, symconst_kind kind);
+ir_node *new_simpleSel (ir_node *store, ir_node *objptr, entity *ent);
+ir_node *new_Sel    (ir_node *store, ir_node *objptr, int arity, ir_node **in,
+                     entity *ent);
+ir_node *new_Call   (ir_node *store, ir_node *callee, int arity, ir_node **in,
+                    type_method *type);
+ir_node *new_Add    (ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_Sub    (ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_Minus  (ir_node *op,  ir_mode *mode);
+ir_node *new_Mul    (ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_Quot   (ir_node *memop, ir_node *op1, ir_node *op2);
+ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2);
+ir_node *new_Div    (ir_node *memop, ir_node *op1, ir_node *op2);
+ir_node *new_Mod    (ir_node *memop, ir_node *op1, ir_node *op2);
+ir_node *new_Abs    (ir_node *op,                ir_mode *mode);
+ir_node *new_And    (ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_Or     (ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_Eor    (ir_node *op1, ir_node *op2, ir_mode *mode);
+ir_node *new_Not    (ir_node *op,                ir_mode *mode);
+ir_node *new_Shl    (ir_node *op,  ir_node *k,   ir_mode *mode);
+ir_node *new_Shr    (ir_node *op,  ir_node *k,   ir_mode *mode);
+ir_node *new_Shrs   (ir_node *op,  ir_node *k,   ir_mode *mode);
+ir_node *new_Rot    (ir_node *op,  ir_node *k,   ir_mode *mode);
+ir_node *new_Cmp    (ir_node *op1, ir_node *op2);
+ir_node *new_Conv   (ir_node *op, ir_mode *mode);
+ir_node *new_Phi    (int arity, ir_node **in, ir_mode *mode);
+ir_node *new_Load   (ir_node *store, ir_node *addr);
+ir_node *new_Store  (ir_node *store, ir_node *addr, ir_node *val);
+ir_node *new_Alloc  (ir_node *store, ir_node *size, type *alloc_type,
+                     where_alloc where);
+ir_node *new_Free   (ir_node *store, ir_node *ptr, ir_node *size,
+                    type *free_type);
+ir_node *new_Sync   (int arity, ir_node **in);
+ir_node *new_Proj   (ir_node *arg, ir_mode *mode, long proj);
+ir_node *new_Tuple  (int arity, ir_node **in);
+ir_node *new_Id     (ir_node *val, ir_mode *mode);
+ir_node *new_Bad    (void);
+
+
+#if USE_EXPICIT_PHI_IN_STACK
+Phi_in_stack *new_Phi_in_stack();
+#endif
+
+/* initialize ir construction */
+void init_cons (void);
+
+
+# endif /* _IRCONS_H_ */
diff --git a/ir/ir/ircons.h.flc b/ir/ir/ircons.h.flc
new file mode 100644 (file)
index 0000000..54bcb58
--- /dev/null
@@ -0,0 +1,9 @@
+
+(fast-lock-cache-data 3 (quote (14625 . 19331)) (quote nil) (quote nil) (quote (t ("^#[        ]*error[        ]+\\(.+\\)" (1 font-lock-warning-face prepend)) ("^#[   ]*\\(import\\|include\\)[       ]*\\(<[^>\"
+]*>?\\)" (2 font-lock-string-face)) ("^#[      ]*define[       ]+\\(\\sw+\\)(" (1 font-lock-function-name-face)) ("^#[         ]*\\(elif\\|if\\)\\>" ("\\<\\(defined\\)\\>[    ]*(?\\(\\sw+\\)?" nil nil (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t))) ("^#[     ]*\\(\\sw+\\)\\>[       !]*\\(\\sw+\\)?" (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t)) ("^\\(\\sw+\\)\\>\\([       ]*<\\([^>
+]+\\)[         *&]*>\\)?\\([   ]*::[   *~]*\\(\\sw+\\)\\)*[    ]*(" (1 (if (or (match-beginning 2) (match-beginning 4)) font-lock-type-face font-lock-function-name-face)) (3 font-lock-type-face nil t) (5 font-lock-function-name-face nil t)) ("\\<\\(bool\\|c\\(har\\|omplex\\)\\|double\\|float\\|int\\|long\\|s\\(hort\\|igned\\)\\|unsigned\\|void\\|\\sw+_t\\|Point\\|Widget\\|[A-Z][a-z][A-Z]\\sw+\\)\\>" (0 font-lock-type-face)) ("\\<\\(operator\\)\\>[    ]*\\(!=\\|%=\\|&[&=]\\|()\\|\\*=\\|\\+[+=]\\|-\\(>\\*\\|[=>-]\\)\\|/=\\|<\\(<=\\|[<=]\\)\\|==\\|>\\(>=\\|[=>]\\)\\|\\[\\]\\|\\^=\\||[=|]\\|[!%&*+,/<=>|~^-]\\)?" (1 font-lock-keyword-face) (2 font-lock-builtin-face nil t)) ("\\<\\(case\\|goto\\)\\>[        ]*\\(-?\\sw+\\)?" (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) (":" ("^[       ]*\\(\\sw+\\)[  ]*:\\($\\|[^:]\\)" (beginning-of-line) (end-of-line) (1 font-lock-constant-face))) ("\\<\\(\\(a\\(sm\\|uto\\)\\|break\\|c\\(atch\\|on\\(st\\|tinue\\)\\)\\|d\\(elete\\|o\\)\\|e\\(lse\\|x\\(p\\(licit\\|ort\\)\\|tern\\)\\)\\|f\\(or\\|riend\\)\\|i\\(f\\|nline\\)\\|mutable\\|new\\|re\\(gister\\|turn\\)\\|s\\(izeof\\|tatic\\|witch\\)\\|t\\(emplate\\|h\\(is\\|row\\)\\|ry\\|ypedef\\)\\|v\\(irtual\\|olatile\\)\\|while\\)\\|\\(c\\(lass\\|onst_cast\\)\\|dynamic_cast\\|enum\\|namespace\\|p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|reinterpret_cast\\|st\\(atic_cast\\|ruct\\)\\|typename\\|u\\(nion\\|sing\\)\\)\\)\\>" (0 font-lock-keyword-face)) ("\\<\\(false\\|true\\)\\>" (0 font-lock-constant-face)) ("\\<\\(bool\\|c\\(har\\|omplex\\)\\|double\\|float\\|int\\|long\\|s\\(hort\\|igned\\)\\|unsigned\\|void\\|\\sw+_t\\|Point\\|Widget\\|[A-Z][a-z][A-Z]\\sw+\\)\\>\\([        ]*<\\([^>
+]+\\)[         *&]*>\\)?\\([   ]*::[   *~]*\\(\\sw+\\)\\)*\\([         *&]+\\(\\sw+\\)\\>\\([  ]*<\\([^>
+]+\\)[         *&]*>\\)?\\([   ]*::[   *~]*\\(\\sw+\\)\\)*\\)*" (5 font-lock-type-face nil t) (font-lock-match-c++-style-declaration-item-and-skip-to-next (goto-char (or (match-beginning 8) (match-end 1))) (goto-char (match-end 1)) (1 (cond ((or (match-beginning 2) (match-beginning 4)) font-lock-type-face) ((and (match-beginning 6) (c-at-toplevel-p)) font-lock-function-name-face) (t font-lock-variable-name-face))) (3 font-lock-type-face nil t) (5 (if (match-beginning 6) font-lock-function-name-face font-lock-variable-name-face) nil t))) ("\\<\\(c\\(lass\\|onst_cast\\)\\|dynamic_cast\\|enum\\|namespace\\|p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|reinterpret_cast\\|st\\(atic_cast\\|ruct\\)\\|typename\\|u\\(nion\\|sing\\)\\)\\>\\([       ]*<\\([^>
+]+\\)[         *&]*>\\)?\\([   ]*::[   *~]*\\(\\sw+\\)\\)*[    ]*\\(\\(\\sw+\\)\\>\\([         ]*<\\([^>
+]+\\)[         *&]*>\\)?\\([   ]*::[   *~]*\\(\\sw+\\)\\)*\\)?" (8 font-lock-type-face nil t) (12 font-lock-type-face nil t) (font-lock-match-c++-style-declaration-item-and-skip-to-next nil nil (1 (cond ((or (match-beginning 2) (match-beginning 4)) font-lock-type-face) ((and (match-beginning 6) (c-at-toplevel-p)) font-lock-function-name-face) (t font-lock-variable-name-face))) (3 font-lock-type-face nil t) (5 (if (match-beginning 6) font-lock-function-name-face font-lock-variable-name-face) nil t))) ("\\(}\\)[    *]*\\sw" (font-lock-match-c++-style-declaration-item-and-skip-to-next (goto-char (match-end 1)) nil (1 font-lock-type-face))) ("^\\(\\(\\sw+\\)\\>\\([  ]*<\\([^>
+]+\\)[         *&]*>\\)?\\([   ]*::[   *~]*\\(\\sw+\\)\\)*[    *&]*\\)+" (font-lock-match-c++-style-declaration-item-and-skip-to-next (goto-char (match-beginning 1)) (goto-char (match-end 1)) (1 (cond ((or (match-beginning 2) (match-beginning 4)) font-lock-type-face) ((match-beginning 6) font-lock-function-name-face) (t font-lock-variable-name-face))) (3 font-lock-type-face nil t) (5 (if (match-beginning 6) font-lock-function-name-face font-lock-variable-name-face) nil t))))) (quote ((font-lock-type-face 40513 40517 40497 40501 40384 40388 40286 40289 40253 40257 40177 40180 39792 39795 38524 38527 38409 38412 38093 38096 38015 38019 37987 37991 37959 37963 37931 37935 37705 37708 37629 37633 37511 37514 36945 36948 34861 34864 34712 34715 34264 34267 33982 33994 33965 33968 33929 33941 33552 33555) (font-lock-function-name-face 40502 40511 40436 40452 40372 40379 40321 40327 40274 40283 40212 40220 40165 40173 40074 40082 39962 39971 39895 39904 39842 39850 39780 39787 39730 39738 39680 39687 39615 39622 39550 39558 39485 39492 39420 39427 39355 39362 39290 39297 39225 39231 39160 39167 39095 39102 39029 39036 38963 38970 38897 38907 38831 38839 38766 38773 38715 38724 38650 38657 38585 38592 38479 38487 38364 38371 38293 38306 38230 38242 38180 38189 38128 38137 38065 38075 38031 38039 38003 38010 37975 37982 37947 37956 37919 37928 37828 37837 37740 37748 37650 37661 37546 37556 37466 37476 37340 37350 37208 37219 37099 37110 37004 37014 36900 36909 36807 36817 36714 36723 36609 36618 36504 36514 36399 36408 36294 36303 36201 36210 36093 36102 35985 35993 35877 35886 35770 35779 35661 35670 35552 35561 35443 35455 35334 35344 35226 35235 35131 35142 35023 35032 34915 34924 34774 34784 34610 34619 34487 34501 34394 34405 34299 34310 34193 34205 34126 34136 34071 34080 33474 33485) (font-lock-keyword-face 33922 33928 33914 33921 33458 33464) (string 33170 33180 33151 33159 33132 33140 33110 33121 33091 33099 33070 33080 33053 33059 33032 33042 33011 33021 32990 33000) (font-lock-variable-name-face 40397 40421 40297 40304 40290 40295 40258 40262 40188 40195 40181 40186 39817 39824 39803 39810 39796 39801 38535 38542 38528 38533 38420 38427 38413 38418 38104 38111 38097 38102 37716 37723 37709 37714 37634 37638 37522 37529 37515 37520 36949 36954 34886 34897 34872 34879 34865 34870 34725 34732 34716 34723 34275 34282 34268 34273 33975 33978 33801 33825 33563 33570 33556 33561 32968 32978 32948 32958) (font-lock-builtin-face 40524 40529 40457 40462 40394 40396 33997 34002 33798 33800 33162 33169 33143 33150 33124 33131 33102 33109 33083 33090 33062 33069 33045 33052 33024 33031 33003 33010 32982 32989 32961 32967 32941 32947) (font-lock-comment-face 40530 40546 40464 40496 37883 37908 37859 37882 34028 34060 34004 34027 33826 33912 33579 33795 33389 33457 33320 33388 33251 33319 33182 33250 823 32936 347 820 1 344))))
diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c
new file mode 100644 (file)
index 0000000..c37eb0e
--- /dev/null
@@ -0,0 +1,552 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** irdump.h: dumping of an intermediate representation graph
+*/
+
+# include <assert.h>
+# include "irdump.h"
+# include "panic.h"
+# include <string.h>
+# include "entity.h"
+# include <stdlib.h>
+# include "array.h"
+# include "irop.h"
+# include "tv.h"
+# include "type_or_entity.h"
+# include "irgwalk.h"
+# include "typewalk.h"
+
+#define DEFAULT_NODE_ATTR ""
+#define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
+#define NODE2TYPE_EDGE_ATTR ""
+#define DEFAULT_TYPE_ATTRIBUTE ""
+#define TYPE_EDGE_ATTR ""
+
+/* file to dump to */
+static FILE *F;
+
+
+/*******************************************************************/
+/* routines to dump information about a single node                */
+/*******************************************************************/
+
+void
+dump_ir_node (ir_node *n)
+{
+  /* dump this node */
+  xfprintf (F, "node: {title: \"%p\" label: ", n);
+
+  switch (n->op->code) {  /* node label */
+  case iro_Start:
+    xfprintf (F, "\"%I\" color: blue ", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+     break;
+  case iro_End:
+    xfprintf (F, "\"%I\" color: blue ", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Block:
+    xfprintf (F, "\"%I\" color: lightyellow ", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Phi:
+    xfprintf (F, "\"%I%I\" color: green", n->op->name, n->mode->name);
+    if (n->mode->code == irm_M)
+      xfprintf (F, DEFAULT_NODE_ATTR " color: green");
+    else
+      xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Const:
+    xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Id:
+    xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Proj:
+    if (n->in[1]->op->code == iro_Cmp) {
+      xfprintf (F, "\"%I%I %s\" color: yellow", n->op->name, n->mode->name,
+                get_pnc_string(n->attr.proj));
+    } else {
+      xfprintf (F, "\"%I%I %ld\"", n->op->name, n->mode->name, n->attr.proj);
+    }
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Conv:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Tuple:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Add:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Sub:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Mul:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Quot:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_DivMod:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Div:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Mod:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_And:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Or:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Eor:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Shl:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Shr:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Abs:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Cmp:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Jmp:
+    xfprintf (F, "\"%I\"", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Cond:
+    xfprintf (F, "\"%I\"", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Call:
+    xfprintf (F, "\"%I\"", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Return:
+    xfprintf (F, "\"%I\"", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Raise:
+    xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Load:
+  case iro_Store:
+    xfprintf (F, "\"%R\"", n);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Alloc:
+    xfprintf (F, "\"%I\" ", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Sel:
+    assert(n->attr.s.ent->kind == k_entity);
+    xfprintf (F, "\"%I ", n->op->name);
+    xfprintf (F, "%s\" ", id_to_str(n->attr.s.ent->name));
+    // xfprintf (F, "\"%I %I\" ", n->op->name, n->attr.s.ent); // GL: doesn't work for some reason.
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_SymConst:
+    assert(get_kind(get_SymConst_type(n)) == k_type_class);
+      //assert(n->attr.i.type->kind == k_type_class);
+    assert(get_class_ident((type_class *)get_SymConst_type(n)));
+    //assert(n->attr.i.type->clss->name);
+    xfprintf (F, "\"%s ", id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
+    //xfprintf (F, "\"%s ", id_to_str(n->attr.i.type->name));
+    // xfprintf (F, "\"%N\" ", n->attr.i.type);  // GL: doesn't work for some reason.
+    switch (n->attr.i.num){
+    case type_tag:
+      xfprintf (F, "tag\" ");
+      break;
+    case size:
+      xfprintf (F, "size\" ");
+      break;
+    default:
+      assert(0);
+      break;
+    }
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  case iro_Sync:
+    xfprintf (F, "\"%I\" ", n->op->name);
+    xfprintf (F, DEFAULT_NODE_ATTR " color: green");
+    break;
+  case iro_Bad:
+    xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
+    xfprintf (F, DEFAULT_NODE_ATTR);
+    break;
+  default:
+    xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
+  }
+  xfprintf (F, "}\n");         /* footer */
+}
+
+
+/* dump the edge to the block this node belongs to */
+void
+dump_ir_block_edge(ir_node *n)  {
+  if (is_no_Block(n))
+    xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+               BLOCK_EDGE_ATTR "}\n", n, get_nodes_Block(n));
+}
+
+
+/* dump edges to our inputs */
+void
+dump_ir_data_edges(ir_node *n)  {
+  int i;
+
+  for (i = 0; i < get_irn_arity(n); i++) {
+    assert(get_irn_n(n, i));
+    xfprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\"",
+             n, get_irn_n(n, i));
+    fprintf (F, " label: \"%d\"", i+1);
+    fprintf (F, "}\n");
+  }
+}
+
+/* dumps the edges between nodes and their type or entity attributes. */
+void dump_node2type_edges (ir_node *n, void *env)
+{
+  assert(n);
+
+  switch (get_irn_opcode(n)) {
+  case iro_SymConst:
+    if (   (get_SymConst_kind(n) == type_tag)
+        || (get_SymConst_kind(n) == size))
+      xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+               NODE2TYPE_EDGE_ATTR "}\n", n, get_SymConst_type(n));
+    break;
+  case iro_Sel:
+    xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+             NODE2TYPE_EDGE_ATTR "}\n", n, get_Sel_entity(n));
+    break;
+  case iro_Call:
+    xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+             NODE2TYPE_EDGE_ATTR "}\n", n, get_Call_type(n));
+    break;
+  case iro_Alloc:
+    xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+             NODE2TYPE_EDGE_ATTR "}\n", n, get_Alloc_type(n));
+    break;
+  case iro_Free:
+    xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+             NODE2TYPE_EDGE_ATTR "}\n", n, get_Free_type(n));
+    break;
+  default:
+    break;
+  }
+}
+
+
+/* dumps a type or entity and it's edges. */
+void
+dump_type_info (type_or_ent *tore, void *env) {
+  int i = 0;  /* to shutup gcc */
+
+  /* dump this type or entity */
+  xfprintf (F, "node: {title: \"%p\" ", tore);
+  xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
+  xfprintf (F, "label: ");
+
+  switch (get_kind(tore)) {
+  case k_entity:
+    {
+      entity *ent = (entity *)tore;
+      xfprintf (F, "\"ent %I\"}\n", get_entity_ident(ent));
+      xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+                " label: \"owner\" "
+               TYPE_EDGE_ATTR "}\n", tore, get_entity_owner(ent));
+      xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+                " label: \"type\" "
+               TYPE_EDGE_ATTR "}\n", tore, get_entity_type(ent));
+    }
+    break;
+  case k_type_class:
+    {
+      type_class *type = (type_class *)tore;
+      xfprintf (F, "\"class %I\"}\n", get_class_ident(type));
+      /* edges !!!??? */
+    }
+    break;
+  case k_type_strct:
+    {
+      type_strct *type = (type_strct *)tore;
+      xfprintf (F, "\"strct %I\"}\n", get_strct_ident(type));
+      /* edges !!!??? */
+    }
+    break;
+  case k_type_method:
+    {
+      type_method *type = (type_method *)tore;
+      xfprintf (F, "\"meth %I\"}\n", get_method_ident(type));
+      for (i = 0; i < get_method_arity(type); i++)
+       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+                 " label: \"param %d\" " TYPE_EDGE_ATTR "}\n",
+                 tore, get_method_param_type(type, i), i);
+      for (i = 0; i < get_method_n_res(type); i++)
+       xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+                 " label: \"res %d\" " TYPE_EDGE_ATTR "}\n",
+                 tore, get_method_res_type(type, i), i);
+    }
+    break;
+  case k_type_union:
+    {
+      type_union *type = (type_union *)tore;
+      xfprintf (F, "\"union %I\"}\n", get_union_ident(type));
+      /* edges !!!??? */
+    }
+    break;
+  case k_type_array:
+    {
+      type_array *type = (type_array *)tore;
+      xfprintf (F, "\"array %I\"}\n", get_array_ident(type));
+      xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+               TYPE_EDGE_ATTR "}\n", tore, get_array_element_type(type), i);
+    }
+    break;
+  case k_type_enumeration:
+    {
+      type_enumeration *type = (type_enumeration *)tore;
+      xfprintf (F, "\"enum %I\"}\n", get_enumeration_ident(type));
+    }
+    break;
+  case k_type_pointer:
+    {
+      type_pointer *type = (type_pointer *)tore;
+      xfprintf (F, "\"ptr %I\"}\n", get_pointer_ident(type));
+      xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
+               TYPE_EDGE_ATTR "}\n", tore,
+               get_pointer_points_to_type(type), i);
+    }
+    break;
+  case k_type_primitive:
+    {
+      type_primitive *type = (type_primitive *)tore;
+      xfprintf (F, "\"prim %I, mode %I\"}\n", get_primitive_ident(type),
+               get_mode_ident(get_primitive_mode(type)));
+    }
+    break;
+  default:
+    break;
+  }
+
+}
+
+/************************************************************************/
+/* open and close vcg file                                              */
+/************************************************************************/
+
+void vcg_open (ir_graph *irg, char *suffix) {
+  char *fname;  /* filename to put the vcg information in */
+  const char *cp;
+  ident *id;
+  int len;
+
+  /** open file for vcg graph */
+  id    = get_entity_ld_name (irg->ent);
+
+  len   = id_to_strlen (id);
+  cp    = id_to_str (id);
+  fname = malloc (len + 5 + strlen(suffix));
+  strcpy (fname, cp);      /* copy the filename */
+  strcat (fname, suffix);  /* append file suffix */
+  strcat (fname, ".vcg");  /* append the .vcg suffix */
+
+  F = fopen (fname, "w");  /* open file for writing */
+  if (!F) {
+    panic ("cannot open %s for writing (%m)", fname);  /* not reached */
+  }
+
+  /* print header */
+  xfprintf (F,
+           "graph: { title: \"ir graph of %s\"\n"
+           "display_edge_labels: yes\n"
+           "layoutalgorithm: mindepth\n"
+           "manhattan_edges: yes\n"
+           "port_sharing: no\n"
+           "orientation: bottom_to_top\n"
+           "classname 1: \"Data\"\n"
+           "classname 2: \"Block\"\n", cp);
+
+  xfprintf (F, "\n");          /* a separator */
+}
+
+void
+vcg_close () {
+  xfprintf (F, "}\n");  /* print footer */
+  fclose (F);           /* close vcg file */
+}
+
+
+
+/************************************************************************/
+/* routines to dump a graph, blocks as conventional nodes.              */
+/************************************************************************/
+
+void
+dump_whole_node (ir_node *n, void* env) {
+  dump_ir_node(n);
+  dump_ir_block_edge(n);
+  dump_ir_data_edges(n);
+}
+
+void
+dump_ir_graph (ir_graph *irg)
+{
+  vcg_open (irg, "");
+
+  /* walk over the graph */
+  irg_walk(irg->end, dump_whole_node, NULL, NULL);
+
+  vcg_close();
+}
+
+/***********************************************************************/
+/* the following routines dump the nodes as attached to the blocks.    */
+/***********************************************************************/
+
+void
+dump_ir_blocks_nodes (ir_node *n, void *env) {
+  ir_node *block = (ir_node *)env;
+
+  if (is_no_Block(n) && get_nodes_Block(n) == block) {
+    dump_ir_node(n);
+    dump_ir_data_edges(n);
+  }
+}
+
+
+void
+dump_ir_block (ir_node *block, void *env) {
+  ir_graph *irg = (ir_graph *)env;
+
+  if (get_irn_opcode(block) == iro_Block) {
+    /* This is a block. So dump the vcg information to make a block. */
+    xfprintf(F, "graph: { title: \"%p\" status:clustered color:lightyellow \n",
+            block);
+    /* dump the blocks edges */
+    dump_ir_data_edges(block);
+
+    /* dump the nodes that go into the block */
+    irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
+
+    /* Close the vcg information for the block */
+    xfprintf(F, "}\n\n");
+  }
+}
+
+void
+dump_ir_block_graph (ir_graph *irg)
+{
+  vcg_open (irg, "");
+
+  /* walk over the blocks in the graph */
+  irg_block_walk(irg->end, dump_ir_block, NULL, irg);
+
+  vcg_close();
+}
+
+
+/***********************************************************************/
+/* the following routines dump a control flow graph                    */
+/***********************************************************************/
+
+
+void
+dump_block_to_cfg (ir_node *block, void *env) {
+  int i;
+  ir_node *pred;
+
+  if (get_irn_opcode(block) == iro_Block) {
+    /* This is a block. Dump a node for the block. */
+    xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
+             block->op->name);
+    /* Dump the edges */
+    for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
+      pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
+      xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" }\n",
+                block, pred);
+    }
+  }
+}
+
+void
+dump_cfg (ir_graph *irg)
+{
+  vcg_open (irg, "-cfg");
+
+  /* walk over the blocks in the graph */
+  irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
+
+  vcg_close();
+}
+
+
+/***********************************************************************/
+/* the following routine dumps all type information                    */
+/***********************************************************************/
+
+
+void
+dump_type_graph (ir_graph *irg)
+{
+  vcg_open (irg, "-type");
+
+  /* walk over the blocks in the graph */
+  type_walk(irg, dump_type_info, NULL, NULL);
+
+  vcg_close();
+}
+
+
+/***********************************************************************/
+/* dumps a graph with type information                                 */
+/***********************************************************************/
+
+
+void
+dump_ir_graph_w_types (ir_graph *irg)
+{
+  vcg_open (irg, "-all");
+
+  /* dump common ir graph */
+  //  irg_block_walk(irg->end, dump_ir_block, NULL, irg);
+  irg_walk(irg->end, dump_whole_node, NULL, NULL);
+  /* dump type info */
+  type_walk(irg, dump_type_info, NULL, NULL);
+  /* dump edges from graph to type info */
+  irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
+
+  vcg_close();
+}
diff --git a/ir/ir/irdump.h b/ir/ir/irdump.h
new file mode 100644 (file)
index 0000000..2ecbe76
--- /dev/null
@@ -0,0 +1,35 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** dump an ir graph, for further use with xvcg
+*/
+
+# ifndef _IRDUMP_H_
+# define _IRDUMP_H_
+
+# include "irnode.h"
+# include "irgraph.h"
+
+/* dump a simple node */
+void dump_ir_node (ir_node *node);
+/* dump the edge to the block this node belongs to */
+void dump_ir_block_edge(ir_node *n);
+/* dump edges to our inputs */
+void dump_ir_data_edges(ir_node *n);
+
+/* dump a hole graph */
+void dump_ir_graph (ir_graph *irg);
+
+/* dump a graph blockwise */
+void dump_ir_block_graph (ir_graph *irg);
+
+/* dump a control flow graph */
+void dump_cfg (ir_graph *irg);
+
+/* dumps the type information reachable from an ir graph. */
+void dump_type_graph (ir_graph *irg);
+
+
+# endif /* _IRDUMP_H_ */
diff --git a/ir/ir/irflag.c b/ir/ir/irflag.c
new file mode 100644 (file)
index 0000000..2095d02
--- /dev/null
@@ -0,0 +1,51 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer
+**
+** irflag --- optimization flags
+*/
+
+# include "irflag.h"
+
+int opt_cse = 0;
+int opt_constant_folding = 1;
+int optimized = 1;
+
+/* set the flags with set_flagname, get the flag with get_flagname */
+
+void
+set_opt_cse (int value)
+{
+  opt_cse = value;
+}
+
+int
+get_opt_cse (void)
+{
+  return opt_cse;
+}
+
+void
+set_opt_constant_folding (int value)
+{
+  opt_constant_folding=value;
+}
+
+int
+get_opt_constant_folding (void)
+{
+  return opt_constant_folding;
+}
+
+void
+set_optimize (int value)
+{
+  optimized = value;
+}
+
+int
+get_optimize (void)
+{
+  return optimized;
+}
diff --git a/ir/ir/irflag.h b/ir/ir/irflag.h
new file mode 100644 (file)
index 0000000..5df905f
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer
+**
+** irflag --- optimization flags
+*/
+
+#ifndef _IRFLAG_H_
+#define _IRFLAG_H_
+
+extern int opt_cse;
+extern int opt_constant_folding;
+
+/* set the flags with set_flagname, get the flag with get_flagname */
+
+void set_opt_cse (int value);
+int  get_opt_cse (void);
+void set_opt_constant_folding (int value);
+int  get_opt_constant_folding (void);
+
+void set_optimize (int value);
+int  get_optimize (void);
+
+#endif
diff --git a/ir/ir/irgmod.c b/ir/ir/irgmod.c
new file mode 100644 (file)
index 0000000..fde51ce
--- /dev/null
@@ -0,0 +1,306 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** irgmod: ir graph modification
+*/
+
+# include "irgmod.h"
+# include "iropt.h"
+
+/*  ir_node * */
+/*  arg_access (ir_mode *mode, long proj) */
+/*  { */
+/*    return new_r_Proj (current_ir_graph, current_ir_graph->start,  */
+/*                  current_ir_graph->args, mode, proj); */
+/*  } */
+
+
+/* these two functions are used in phi_merge, but defined in ircons.c */
+inline ir_node * get_r_value_internal (ir_node *block,
+                                      int pos, ir_mode *mode);
+inline ir_node * new_r_Phi_in (ir_graph *irg, ir_node *block, ir_mode *mode,
+                              ir_node **in, int ins);
+
+/** This function computes the predecessors for a real Phi node, and then
+    allocates and returns this node.  The routine called to allocate the
+    node might optimize it away and return a real value, or even a pointer
+    to a deallocated Phi node on top of the obstack!
+    This function is called with an in-array of proper size. **/
+static inline ir_node *
+phi_merge (ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins)
+{
+  ir_node *prevBlock, *res;
+  int i;
+
+  /* This loop goes to all predecessor blocks of the block the Phi node is in
+     and there finds the operands of the Phi node by calling get_r_value_internal. */
+  for (i = 1;  i <= ins;  ++i) {
+    assert (block->in[i]);
+    prevBlock = block->in[i]->in[0]; /* go past control flow op to prev block */
+    assert (prevBlock);
+    nin[i-1] = get_r_value_internal (prevBlock, pos, mode);
+  }
+
+  /* After collecting all predecessors into the array nin a new Phi node
+     with these predecessors is created.  This constructor contains an
+     optimization: If all predecessors of the Phi node are identical it
+     returns the only operand instead of a new Phi node.  If the value
+     passes two different control flow edges without being defined, and
+     this is the second path treated, a pointer to the node that will be
+     allocated for the first path (recurstion) is returned.  We already
+     know the address of this node, as it is the next node to be allocated
+     and will be placed on top of the obstack. (The obstack is a _stack_!) */
+  res = new_r_Phi_in (current_ir_graph, block, mode, nin, ins);
+
+  /* Now we now the value "pos" and can enter it in the array with
+     all known local variables.  Attention: this might be a pointer to
+     a node, that later will be allocated!!! See new_r_Phi_in.
+     If this is called in mature, after some set_value in the same block,
+     the proper value must not be overwritten:
+     The call order
+       get_value    (makes Phi0, put's it into graph_arr)
+       set_value    (overwrites Phi0 in graph_arr)
+       mature_block (upgrades Phi0, puts it again into graph_arr, overwriting
+                     the proper value.)
+     fails. */
+  if (!block->attr.block.graph_arr[pos]) {
+    block->attr.block.graph_arr[pos] = res;
+  } else {
+    //  printf(" value already computed by %s\n",
+    //  id_to_str(block->attr.block.graph_arr[pos]->op->name));
+  }
+
+  return res;
+}
+
+
+/* this function is used in get_r_value_internal, but defined in ircons.c */
+inline ir_node * new_r_Phi0 (ir_graph *irg, ir_node *block, ir_mode *mode);
+
+
+/* This function returns the last definition of a variable.  In case
+   this variable was last defined in a previous block, Phi nodes are
+   inserted.  If the part of the firm graph containing the definition
+   is not yet constructed, a dummy Phi node is returned. */
+inline ir_node *
+get_r_value_internal (ir_node *block, int pos, ir_mode *mode)
+{
+  ir_node *res;
+  /* There are 4 cases to treat.
+
+     1. The block is not mature and we visit it the first time.  We can not
+        create a proper Phi node, therefore a Phi0, i.e., a Phi without
+        predecessors is returned.  This node is added to the linked list (field
+        "link") of the containing block to be completed when this block is
+        matured. (Comlpletion will add a new Phi and turn the Phi0 into a Id
+        node.)
+
+     2. The value is already known in this block, graph_arr[pos] is set and we
+        visit the block the first time.  We can return the value without
+        creating any new nodes.
+
+     3. The block is mature and we visit it the first time.  A Phi node needs
+        to be created (phi_merge).  If the Phi is not needed, as all it's
+        operands are the same value reaching the block through different
+        paths, it's optimizes away and the value itself is returned.
+
+     4. The block is mature, and we visit it the second time.  Now two
+        subcases are possible:
+        * The value was computed completely the last time we were here.
+          This is the case if there is no loop.  We can return the proper value.
+        * The recursion that visited this node and set the flag did not
+          return yet.  We are computing a value in a loop and need to
+          break the recursion without knowing the result yet.
+        There is no simple check for the second subcase.  Therefore we check
+        for a second visit and treat all such cases as the second subcase.
+        Anyways, the basic situation is the same:  we reached a block
+        on two paths without finding a definition of the value:  No Phi
+        nodes are needed on both paths.
+        We return this information "Two paths, no Phi needed" by a very tricky
+        implementation that relies on the fact that an obstack is a stack and
+        will return a node with the same address on different allocations.
+        Look also at phi_merge and get_r_phi_in to understand this.
+  */
+
+  /* case 4 -- already visited. */
+  if (block->visit == ir_visited) return NULL;
+
+  /* visited the first time */
+  block->visit = ir_visited;
+
+  /* Get the local valid value */
+  res = block->attr.block.graph_arr[pos];
+
+  /* case 2 -- If the value is actually computed, return it. */
+  if (res) { return res;};
+
+  if (block->attr.block.matured) { /* case 3 */
+
+    /* The Phi has the same amount of ins as the corresponding block. */
+    int ins = get_irn_arity(block); // ARR_LEN (block->in)-1;
+    ir_node **nin;
+    NEW_ARR_A (ir_node *, nin, ins);
+
+    /* Phi merge collects the predecessors and then creates a node. */
+    res = phi_merge (block, pos, mode, nin, ins);
+
+  } else {  /* case 1 */
+    /* The block is not mature, we don't know how many in's are needed.  A Phi
+       with zero predecessors is created.  Such a Phi node is called Phi0
+       node.  (There is also an obsolete Phi0 opcode.) The Phi0 is then added
+       to the list of Phi0 nodes in this block to be matured by mature_block
+       later.
+       The Phi0 has to remember the pos of it's internal value.  If the real Phi
+       is computed, pos is used to update the array with the local values. */
+
+    res = new_r_Phi0 (current_ir_graph, block, mode);
+    res->attr.phi0_pos = pos;
+    res->link = block->link;
+    block->link = res;
+  }
+
+  /* If we get here, the frontend missed a use-before-definition error */
+  if (!res) {
+    /* Error Message */
+    printf("Error: no value set\n");
+    assert (mode->code >= irm_f && mode->code <= irm_p);
+    res = new_r_Const (current_ir_graph, block, mode,
+                      tarval_mode_null[mode->code]);
+  }
+
+  /* The local valid value is available now. */
+  block->attr.block.graph_arr[pos] = res;
+
+  return res;
+}
+
+
+/* add an adge to a jmp node */
+void
+add_in_edge (ir_node *block, ir_node *jmp)
+{
+  if (block->attr.block.matured) {
+    printf("Error: Block already matured!\n");
+  }
+  else {
+    assert (jmp != NULL);
+    ARR_APP1 (ir_node *, block->in, jmp);
+  }
+}
+
+
+/****************************/
+/* parameter administration */
+
+/* get a value from the parameter array from the current block by its index */
+ir_node *
+get_value (int pos, ir_mode *mode)
+{
+  ++ir_visited;
+  return get_r_value_internal (current_ir_graph->current_block, pos + 1, mode);
+}
+
+
+/* set a value at position pos in the parameter array from the current block */
+inline void
+set_value (int pos, ir_node *value)
+{
+  current_ir_graph->current_block->attr.block.graph_arr[pos + 1] = value;
+}
+
+
+/* get the current store */
+inline ir_node *
+get_store (void)
+{
+  /* GL: one could call get_value instead */
+  ++ir_visited;
+  return get_r_value_internal (current_ir_graph->current_block, 0, mode_M);
+}
+
+
+/* set the current store */
+inline void
+set_store (ir_node *store)
+{
+  /* GL: one could call set_value instead */
+  current_ir_graph->current_block->attr.block.graph_arr[0] = store;
+}
+
+/** Finalize a Block node, when all control flows are known.  */
+/** Acceptable parameters are only Block nodes.               */
+void
+mature_block (ir_node *block)
+{
+
+  int ins;
+  ir_node *n, **nin;
+  ir_node *next;
+
+  assert (get_irn_opcode(block) == iro_Block);
+
+  if (!get_Block_matured(block)) {
+
+    /* turn the dynamic in-array into a static one. */
+    ins = ARR_LEN (block->in)-1;
+    NEW_ARR_A (ir_node *, nin, ins);
+
+    /* GL, 7.2.2000.  seems to be not complete. added this: but does'nt work.*
+    memcpy (nin, block->in, sizeof (ir_node *) * ins);
+    block->in = nin;
+    */
+
+    /* Traverse a chain of Phi nodes attached to this block and mature these, too. **/
+    for (n = block->link;  n;  n=next) {
+      ir_visited++;
+      next = n->link;
+      exchange (n, phi_merge (block, n->attr.phi0_pos, n->mode, nin, ins));
+    }
+
+    block->attr.block.matured = 1;
+
+    block = optimize_in_place(block);
+    ir_vrfy(block);
+  }
+
+}
+
+/* changing the current block */
+void
+switch_block (ir_node *target)
+{
+  current_ir_graph->current_block = target;
+}
+
+
+void
+turn_into_tuple (ir_node *node, int arity)
+{
+  assert(node);
+  set_irn_op(node, op_Tuple);
+  if (get_irn_arity(node) == arity) {
+    /* keep old array */
+  } else {
+    /* allocate new array, remove old one. */
+    /* !!!??? free old in_array */
+    node->in = NEW_ARR_D (ir_node *, current_ir_graph->obst, arity+1);
+  }
+}
+
+
+
+/* Insert irnode `new' in place of irnode `old'
+   Since `new' may be bigger than `old' replace `old'
+   by an op_Id which is smaller than everything */
+inline void
+exchange (ir_node *old, ir_node *new)
+{
+  ir_node *block = old->in[0];
+
+  old->op = op_Id;
+  old->in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 2);
+  old->in[0] = block;
+  old->in[1] = new;
+}
diff --git a/ir/ir/irgmod.h b/ir/ir/irgmod.h
new file mode 100644 (file)
index 0000000..513a011
--- /dev/null
@@ -0,0 +1,53 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** irgmod.h: ir graph modification*/
+
+# include "irgraph.h"
+# include "ircons.h"
+# include "array.h"
+# include "misc.h"
+
+/* ir_node *arg_access (ir_mode *mode, long proj); */
+
+
+inline ir_node *get_r_value_internal (ir_node *block, int pos, ir_mode *mode);
+
+
+/** Needed only during ir_graph construction. Should all go into
+    ircons.ch **/
+
+/* Read a store.
+   Use this function to get the most recent version of the store (type M).
+   Internally it does the same as get_value. */
+ir_node *get_store (void);
+
+/* write a store */
+void set_store (ir_node *store);
+
+/* add a control flow edge */
+void add_in_edge (ir_node *block, ir_node *jmp);
+
+/* read a value from the array with the local variables */
+ir_node *get_value (int pos, ir_mode *mode);
+
+/* write a value in the array with the local variables */
+void set_value (int pos, ir_node *value);
+
+/* fixes the number of predecessors of a block. */
+void mature_block (ir_node *block);
+
+/* sets current block */
+void switch_block (ir_node *target);
+
+
+/** always useful, e.g. for optimizations.  **/
+/* turns a node into a tuple. The tuples predecessors have to be
+   set by hand. */
+void turn_into_tuple (ir_node *node, int arity);
+
+/* exchanges two nodes by conserving edges leaving old (i.e., pointers
+   pointing to old. */
+inline void exchange (ir_node *old, ir_node *new);
diff --git a/ir/ir/irgraph.c b/ir/ir/irgraph.c
new file mode 100644 (file)
index 0000000..5ded6b6
--- /dev/null
@@ -0,0 +1,220 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+**
+*/
+
+# include "ircons.h"
+# include "irgraph.h"
+# include "iropt.h"
+# include "array.h"
+# include "irgmod.h"
+
+ir_graph *current_ir_graph;
+
+unsigned long ir_visited = 0;
+unsigned long block_visited = 0;
+
+
+/* Allocates a list of nodes:
+    - The start block containing a start node and Proj nodes for it's four
+      results (X, M, P, Tuple).
+    - The end block containing an end node. This block is not matured after
+      new_ir_graph as predecessors need to be added to it.
+    - The current block, which is empty and also not matured.
+   Further it allocates several datastructures needed for graph construction
+   and optimization.
+*/
+ir_graph *
+new_ir_graph (entity *ent, int params)
+{
+  ir_graph *res;
+  ir_node *first_block;
+  ir_node *projX;
+
+  res = (ir_graph *) malloc (sizeof (ir_graph));
+  current_ir_graph = res;
+
+  /** Internal information for graph construction either held in the graph or
+  *** initialized for each graph. **/
+  res->params = params + 1;  /* number of local variables that are never
+                                dereferenced in this graph plus one for
+                               the store. This is not the number of parameters
+                                to the procedure!  */
+#if USE_EXPICIT_PHI_IN_STACK
+  res->Phi_in_stack = new_Phi_in_stack();  /* A stack needed for automatic Phi
+                                generation */
+#endif
+  //???!! turn the Phi_in_stack into a field of ir_graph??
+  res->obst      = (struct obstack *) xmalloc (sizeof (struct obstack));
+  obstack_init (res->obst);
+  res->value_table = new_identities (); /* Symbol table for local variables
+                                          of this procedure */
+
+  /** Type inforamtion for the procedure of the graph **/
+  res->ent = ent;
+
+  /** Nodes needed in every graph **/
+  res->end_block = new_Block ();
+  res->end       = new_End ();
+
+  res->start_block = new_Block ();
+  res->start     = new_Start ();
+  res->bad       = new_ir_node (res, res->start_block, op_Bad, mode_T, 0, NULL);
+
+  /* Proj results of start node */
+  projX        = new_Proj (res->start, mode_X, pns_initial_exec);
+  set_store (new_Proj (res->start, mode_M, pns_global_store));
+  res->frame   = new_Proj (res->start, mode_p, pns_frame_base);
+  res->dataseg = new_Proj (res->start, mode_p, pns_globals);
+  res->args    = new_Proj (res->start, mode_T, pns_args);
+
+  add_in_edge(res->start_block, projX);
+  // The code generation needs it. leave it in now.
+  // Use of this edge is matter of discussion, unresolved. Also possible:
+  // add_in_edge(res->start_block, res->start_block), but invalid typed.
+
+  mature_block (res->current_block);
+
+  /** Make a block to start with **/
+  first_block = new_Block ();
+  add_in_edge (first_block, projX);
+
+  return res;
+}
+
+/* access routines for all ir_graph attributes */
+
+ir_node *
+get_start_block_of_irgraph (ir_graph *irg)
+{
+  return irg->start_block;
+}
+
+void
+set_start_block_of_irgraph (ir_graph *irg, ir_node *node)
+{
+  irg->start_block = node;
+}
+
+ir_node *
+get_start_of_irgraph (ir_graph *irg)
+{
+  return irg->start;
+}
+
+void
+set_start_of_irgraph(ir_graph *irg, ir_node *node)
+{
+  irg->start = node;
+}
+
+ir_node *
+get_end_block_of_irgraph (ir_graph *irg)
+{
+  return irg->end_block;
+}
+
+void
+set_end_block_of_irgraph (ir_graph *irg, ir_node *node)
+{
+  irg->end_block = node;
+}
+
+ir_node *
+get_end_of_irgraph (ir_graph *irg)
+{
+  return irg->end;
+}
+
+void
+set_end_of_irgraph (ir_graph *irg, ir_node *node)
+{
+  irg->end = node;
+}
+
+ir_node *
+get_cstore_of_irgraph (ir_graph *irg)
+{
+  return irg->cstore;
+}
+
+void
+set_cstore_of_irgraph (ir_graph *irg, ir_node *node)
+{
+  irg->cstore = node;
+}
+
+ir_node *
+get_frame_of_irgraph (ir_graph *irg)
+{
+  return irg->frame;
+}
+
+void
+set_frame_of_irgraph(ir_graph *irg, ir_node *node)
+{
+  irg->frame = node;
+}
+
+ir_node *
+get_args_of_irgraph (ir_graph *irg)
+{
+  return irg->args;
+}
+
+void
+set_args_of_irgraph(ir_graph *irg, ir_node *node)
+{
+  irg->args = node;
+}
+
+ir_node *
+get_bad_of_irgraph (ir_graph *irg)
+{
+  return irg->bad;
+}
+
+void
+set_bad_of_irgraph(ir_graph *irg, ir_node *node)
+{
+  irg->bad = node;
+}
+
+ir_node *
+get_current_block_of_irgraph (ir_graph *irg)
+{
+  return irg->current_block;
+}
+
+void
+set_current_block_of_irgraph(ir_graph *irg, ir_node *node)
+{
+  irg->current_block = node;
+}
+
+entity *
+get_ent_of_irgraph(ir_graph *irg)
+{
+  return irg->ent;
+}
+
+void
+set_ent_of_irgraph(ir_graph *irg, entity *ent)
+{
+  irg->ent = ent;
+}
+
+int
+get_params_of_irgraph(ir_graph *irg)
+{
+  return irg->params;
+}
+
+void
+set_params_of_irgraph(ir_graph *irg, int params)
+{
+  irg->params = params;
+}
diff --git a/ir/ir/irgraph.h b/ir/ir/irgraph.h
new file mode 100644 (file)
index 0000000..e6c424d
--- /dev/null
@@ -0,0 +1,96 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** irgraph.h: ir graph construction
+*/
+
+# ifndef _IRGRAPH_H_
+# define _IRGRAPH_H_
+
+/* # include "lib/obstack.h" */
+
+
+# include "irnode.h"
+# include "obst.h"
+# include "tv.h"
+# include "pset.h"
+
+/* ir_graph holds all information for a procedure */
+typedef struct {
+  struct entity  *ent;             /* The entity of this procedure, i.e., the
+                                      type of the procedure and the class it
+                                      belongs to. */
+  struct ir_node *start_block;     /* block the start node will belong to */
+  struct ir_node *start;          /* start node of this ir_graph */
+  struct ir_node *end_block;       /* block the end node will belong to */
+  struct ir_node *end;            /* end node of this ir_graph */
+  struct ir_node *cstore;         /* constant store */
+  struct ir_node *frame;          /* method's frame */
+#if UEBPRAKT
+  struct ir_node *dataseg;         /* pointer to the data segment */
+#endif
+  struct ir_node *args;            /* methods arguments */
+  struct ir_node *bad;            /* bad node of this ir_graph, the one and
+                                      only in this graph */
+  struct obstack *obst;                   /* obstack where all of the ir_nodes live */
+#if USE_EXPICIT_PHI_IN_STACK
+  struct Phi_in_stack *Phi_in_stack; /* needed for automatic Phi construction */
+#endif
+  struct ir_node *current_block;   /* block for newly gen_*()-erated ir_nodes */
+  int params;                      /* number of local variable in this procedure */
+  // should be n_loc or so, params is ambiguous.
+  pset *value_table;               /* value table for global value numbering
+                                     for optimizing use in iropt.c */
+} ir_graph;
+
+extern ir_graph *current_ir_graph;
+
+/* create a new ir graph */
+ir_graph *new_ir_graph (entity *ent, int params);
+
+extern unsigned long ir_visited;
+extern unsigned long block_visited;
+
+/* access routines for all ir_graph attributes */
+
+ir_node *get_start_block_of_irgraph (ir_graph *irg);
+void set_start_block_of_irgraph (ir_graph *irg, ir_node *node);
+
+ir_node *get_start_of_irgraph (ir_graph *irg);
+void set_start_of_irgraph(ir_graph *irg, ir_node *node);
+
+ir_node *get_end_block_of_irgraph (ir_graph *irg);
+void set_end_block_of_irgraph (ir_graph *irg, ir_node *node);
+
+ir_node *get_end_of_irgraph (ir_graph *irg);
+void set_end_of_irgraph (ir_graph *irg, ir_node *node);
+
+ir_node *get_cstore_of_irgraph (ir_graph *irg);
+void set_cstore_of_irgraph (ir_graph *irg, ir_node *node);
+
+ir_node *get_frame_of_irgraph (ir_graph *irg);
+void set_frame_of_irgraph (ir_graph *irg, ir_node *node);
+
+ir_node *get_args_of_irgraph (ir_graph *irg);
+void set_args_of_irgraph (ir_graph *irg, ir_node *node);
+
+ir_node *get_bad_of_irgraph (ir_graph *irg);
+void set_bad_of_irgraph (ir_graph *irg, ir_node *node);
+
+/* not implemented yet
+struct obstack *get_obst_of_irgraph (ir_graph *irg);
+void set_obst_of_irgraph (ir_graph *irg, struct obstack *obst);
+*/
+
+ir_node *get_current_block_of_irgraph (ir_graph *irg);
+void set_current_block_of_irgraph (ir_graph *irg, ir_node *node);
+
+entity *get_ent_of_irgraph (ir_graph *irg);
+void set_ent_of_irgraph (ir_graph *irg, entity *ent);
+
+int get_params_of_irgraph (ir_graph *irg);
+void set_params_of_irgraph (ir_graph *irg, int params);
+
+# endif /* _IRGRAPH_H_ */
diff --git a/ir/ir/irgwalk.c b/ir/ir/irgwalk.c
new file mode 100644 (file)
index 0000000..1b6c2ab
--- /dev/null
@@ -0,0 +1,100 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Author: Boris Boesler
+**
+** traverse an ir graph
+** - execute the pre function before recursion
+** - execute the post function after recursion
+*/
+
+# include "irnode.h"
+# include "irgraph.h" /* ir_visited */
+
+
+void irg_walk_2(ir_node *node,
+             void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
+             void *env)
+{
+  int i;
+
+  assert(node);
+  if(node->visit < ir_visited) {
+    node->visit = ir_visited;
+    if(pre) {
+      pre(node, env);
+    }
+
+    if (is_no_Block(node))
+      irg_walk_2(get_nodes_Block(node), pre, post, env);
+    for(i = get_irn_arity(node) - 1; i >= 0; --i) {
+      irg_walk_2(get_irn_n(node, i), pre, post, env);
+    }
+
+    if(post)
+      post(node, env);
+  }
+  return;
+}
+
+
+void irg_walk(ir_node *node,
+             void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
+             void *env)
+{
+  assert(node);
+  ++ir_visited;
+  irg_walk_2(node, pre, post, env);
+  return;
+}
+
+/***************************************************************************/
+void irg_block_walk_2(ir_node *node,
+                     void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
+                     void *env)
+{
+  int i;
+
+  assert(get_irn_opcode(node) == iro_Block);
+
+
+  if(get_Block_block_visit(node) < block_visited) {
+    set_Block_block_visit(node, block_visited);
+
+    if(pre)
+      pre(node, env);
+
+    for(i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
+
+      /* find the corresponding predecessor block. */
+      ir_node *pred = skip_Proj(get_Block_cfgpred(node, i));
+      /* GL: I'm not sure whether this assert must go through.  There
+         could be Id chains?? */
+      assert(is_cfop(pred) || is_fragile_op(pred));
+      pred = get_nodes_Block(pred);
+      assert(get_irn_opcode(pred) == iro_Block);
+
+      /* recursion */
+      irg_block_walk_2(pred, pre, post, env);
+    }
+
+    if(post)
+      post(node, env);
+  }
+  return;
+}
+
+
+/* walks only over Block nodes in the graph.  Has it's own visited
+   flag, so that it can be interleaved with the other walker.         */
+void irg_block_walk(ir_node *node,
+                   void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
+                   void *env)
+{
+  assert(node);
+  ++block_visited;
+  if (is_no_Block(node)) node = get_nodes_Block(node);
+  assert(get_irn_opcode(node)  == iro_Block);
+  irg_block_walk_2(node, pre, post, env);
+  return;
+}
diff --git a/ir/ir/irgwalk.h b/ir/ir/irgwalk.h
new file mode 100644 (file)
index 0000000..61096d1
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Author: Boris Boesler
+**
+** traverse an ir graph
+** - execute the pre function before recursion
+** - execute the post function after recursion
+*/
+
+
+
+# ifndef _IRGWALK_H_
+# define _IRGWALK_H_
+
+# include "irnode.h"
+
+void irg_walk(ir_node *node,
+             void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
+             void *env);
+
+/* walks only over Block nodes in the graph.  Has it's own visited
+   flag, so that it can be interleaved with the other walker.         */
+void irg_block_walk(ir_node *node,
+                   void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
+                   void *env);
+
+
+# endif /* _IRGWALK_H_ */
diff --git a/ir/ir/irmode.c b/ir/ir/irmode.c
new file mode 100644 (file)
index 0000000..9fe2f5c
--- /dev/null
@@ -0,0 +1,490 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# include "irmode.h"
+# include <malloc.h>
+# include <stddef.h>
+# include "tv.h"
+
+ir_mode *mode_T;
+ir_mode *mode_f;
+ir_mode *mode_d;
+ir_mode *mode_c;
+ir_mode *mode_C;
+ir_mode *mode_h;
+ir_mode *mode_H;
+ir_mode *mode_i;
+ir_mode *mode_I;
+ir_mode *mode_l;
+ir_mode *mode_L;
+ir_mode *mode_B;
+ir_mode *mode_b;
+ir_mode *mode_p;
+ir_mode *mode_s;
+ir_mode *mode_S;
+ir_mode *mode_X;
+ir_mode *mode_M;
+ir_mode *mode_R;
+ir_mode *mode_Z;
+
+
+void
+init_mode (void)
+{
+  /* allocate all modes */
+  mode_T = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_f = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_d = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_c = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_C = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_h = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_H = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_i = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_I = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_l = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_L = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_B = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_b = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_p = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_s = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_S = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_X = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_M = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_R = (ir_mode *) malloc (sizeof (ir_mode));
+  mode_Z = (ir_mode *) malloc (sizeof (ir_mode));
+
+  mode_T->code = irm_T;
+  mode_f->code = irm_f;
+  mode_d->code = irm_d;
+  mode_c->code = irm_c;
+  mode_C->code = irm_C;
+  mode_h->code = irm_h;
+  mode_H->code = irm_H;
+  mode_i->code = irm_i;
+  mode_I->code = irm_I;
+  mode_l->code = irm_l;
+  mode_L->code = irm_L;
+  mode_B->code = irm_B;
+  mode_b->code = irm_b;
+  mode_p->code = irm_p;
+  mode_s->code = irm_s;
+  mode_S->code = irm_S;
+  mode_X->code = irm_X;
+  mode_M->code = irm_M;
+  mode_R->code = irm_R;
+  mode_Z->code = irm_Z;
+
+  /* initialize all modes */
+
+  mode_T->name = id_from_str ("T", 1);
+  mode_T->fsigned = 0;
+  mode_T->ffloat = 0;
+
+  /* float */
+  mode_f->name = id_from_str ("f", 1);
+  mode_f->fsigned = 1;
+  mode_f->ffloat = 1;
+
+  /* double */
+  mode_d->name = id_from_str ("d", 1);
+  mode_d->fsigned = 1;
+  mode_d->ffloat = 1;
+
+  /* signed char */
+  mode_c->name = id_from_str ("c", 1);
+  mode_c->fsigned = 1;
+  mode_c->ffloat = 0;
+  mode_c->ld_align = 0;
+  mode_c->size = 1;
+  mode_c->min = tarval_from_long (mode_l, 0xffffff80);
+  mode_c->max = tarval_from_long (mode_l, 0x0000007f);
+  mode_c->null = tarval_from_long (mode_c, 0);
+
+  /* unsigned char */
+  mode_C->name = id_from_str ("C", 1);
+  mode_C->fsigned = 0;
+  mode_C->ffloat = 0;
+  mode_C->ld_align = 0;
+  mode_C->size = 1;
+  mode_C->min = tarval_from_long (mode_L, 0x00000000);
+  mode_C->max = tarval_from_long (mode_L, 0x000000ff);
+  mode_C->null = tarval_from_long (mode_C, 0);
+
+  /* signed short integer */
+  mode_h->name = id_from_str ("h", 1);
+  mode_h->fsigned = 1;
+  mode_h->ffloat = 0;
+  mode_h->ld_align = 1;
+  mode_h->size = 4;
+  mode_h->min = tarval_from_long (mode_l, 0xffff8000);
+  mode_h->max = tarval_from_long (mode_l, 0x00007fff);
+  mode_h->null = tarval_from_long (mode_h, 0);
+
+  /* unsigened short integer */
+  mode_H->name = id_from_str ("H", 1);
+  mode_H->fsigned = 0;
+  mode_H->ffloat = 0;
+  mode_H->ld_align = 1;
+  mode_H->size = 4;
+  mode_H->min = tarval_from_long (mode_L, 0x00000000);
+  mode_H->max = tarval_from_long (mode_L, 0x0000ffff);
+  mode_H->null = tarval_from_long (mode_H, 0);
+
+  /* signed integer */
+  mode_i->name = id_from_str ("i", 1);
+  mode_i->fsigned = 1;
+  mode_i->ffloat = 0;
+  mode_i->ld_align = 2;
+  mode_i->size = 4;
+  mode_i->min = tarval_from_long (mode_l, 0x80000000);
+  mode_i->max = tarval_from_long (mode_l, 0x7fffffff);
+  mode_i->null = tarval_from_long (mode_i, 0);
+
+  /* unsigned integer */
+  mode_I->name = id_from_str ("I", 1);
+  mode_I->fsigned = 0;
+  mode_I->ffloat = 0;
+  mode_I->ld_align = 2;
+  mode_I->size = 4;
+  mode_I->min = tarval_from_long (mode_L, 0x00000000);
+  mode_I->max = tarval_from_long (mode_L, 0xffffffff);
+  mode_I->null = tarval_from_long (mode_I, 0);
+
+  /* signed long integer */
+  mode_l->name = id_from_str ("l", 1);
+  mode_l->fsigned = 1;
+  mode_l->ffloat = 0;
+  mode_l->ld_align = 2;
+  mode_l->size = 4;
+  mode_l->min = tarval_from_long (mode_l, 0x80000000);
+  mode_l->max = tarval_from_long (mode_l, 0x7fffffff);
+  mode_I->null = tarval_from_long (mode_l, 0);
+
+  /* unsigned long integer */
+  mode_L->name = id_from_str ("L", 1);
+  mode_L->fsigned = 0;
+  mode_L->ffloat = 0;
+  mode_L->ld_align = 2;
+  mode_L->size = 4;
+  mode_L->min = tarval_from_long (mode_L, 0x00000000);
+  mode_L->max = tarval_from_long (mode_L, 0xffffffff);
+  mode_L->null = tarval_from_long (mode_L, 0);
+
+  /* universal bits */
+  mode_B->name = id_from_str ("B", 1);
+  mode_B->fsigned = 0;
+  mode_B->ffloat = 0;
+
+  /* boolean */
+  mode_b->name = id_from_str ("b", 1);
+  mode_b->fsigned = 0;
+  mode_b->ffloat = 0;
+
+  /* pointer */
+  mode_p->name = id_from_str ("p", 1);
+  mode_p->fsigned = 0;
+  mode_p->ffloat = 0;
+  mode_p->ld_align = 2;
+  mode_p->size = 4;
+  mode_p->min = tarval_from_long (mode_L, 0x00000000);
+  mode_p->max = tarval_from_long (mode_L, 0xffffffff);
+  mode_p->null = tarval_from_long (mode_p, 0);
+
+  mode_s->name = id_from_str ("s", 1);
+  mode_s->fsigned = 0;
+  mode_s->ffloat = 0;
+
+  mode_S->name = id_from_str ("S", 1);
+  mode_S->fsigned = 0;
+  mode_S->ffloat = 0;
+
+  mode_X->name = id_from_str ("X", 1);
+  mode_X->fsigned = 0;
+  mode_X->ffloat = 0;
+
+  mode_M->name = id_from_str ("M", 1);
+  mode_M->fsigned = 0;
+  mode_M->ffloat = 0;
+
+  mode_R->name = id_from_str ("R", 1);
+  mode_R->fsigned = 0;
+  mode_R->ffloat = 0;
+
+  mode_Z->name = id_from_str ("Z", 1);
+  mode_Z->fsigned = 1;
+  mode_Z->ffloat = 0;
+
+}
+
+/* Functions for the direct access to all attributes od a ir_mode */
+
+modecode
+get_modecode_of_mode (ir_mode *mode)
+{
+  return mode->code;
+}
+
+/*
+inline void
+set_modecode_of_mode (ir_mode *mode, modecode code)
+{
+  mode->code = code;
+}
+*/
+
+ident *
+get_mode_ident (ir_mode *mode)
+{
+  return mode->name;
+}
+
+/*
+inline void
+set_ident_of_mode (ir_mode *mode, ident *name)
+{
+  mode->name = name;
+}
+*/
+
+int
+get_size_of_mode (ir_mode *mode)
+{
+  return mode->size;
+}
+/*
+inline void
+set_size_of_mode (ir_mode *mode, int size)
+{
+  mode->size = size;
+}
+*/
+
+int
+get_ld_align_of_mode (ir_mode *mode)
+{
+  return mode->ld_align;
+}
+
+/*
+inline void
+set_ld_align_of_mode (ir_mode *mode, int ld_align)
+{
+  mode->ld_align = ld_align;
+}
+*/
+
+tarval *
+get_min_of_mode (ir_mode *mode)
+{
+  return mode->min;
+}
+
+/*
+inline void
+set_min_of_mode (ir_mode *mode, struct tarval *min)
+{
+mode->min = min;
+}
+*/
+
+tarval *
+get_max_of_mode (ir_mode *mode)
+{
+  return mode->max;
+}
+
+/*
+inline void
+set_max_of_mode (ir_mode *mode, struct tarval *max)
+{
+  mode->max = max;
+}
+*/
+
+tarval *
+get_null_of_mode (ir_mode *mode)
+{
+  return mode->null;
+}
+
+/*
+inline void
+set_null_of_mode (ir_mode *mode, struct tarval *null)
+{
+  mode->null = null;
+}
+*/
+
+unsigned
+get_fsigned_of_mode (ir_mode *mode)
+{
+  return mode->fsigned;
+}
+
+/*
+inline voida
+set_fsigned_of_mode (ir_mode *mode, unsigned fsigned)
+{
+  mode->fsigned = fsigned;
+}
+*/
+
+unsigned
+get_ffloat_of_mode (ir_mode *mode)
+{
+  return mode->ffloat;
+}
+
+/*
+inline void
+set_ffloat_of_mode (ir_mode *mode, unsigned ffloat)
+{
+  mode->ffloat = ffloat;
+}
+*/
+
+/* Functions to check, whether a modecode is signed, float, int, num, data,
+   datab or dataM. For more exact definitions read the corresponding pages
+   in the firm documentation or the followingenumeration
+
+   The set of "float" is defined as:
+   ---------------------------------
+   float = {irm_f, irm_d}
+
+   The set of "int" is defined as:
+   -------------------------------
+   int   = {irm_c, irm_C, irm_h, irm_H, irm_i, irm_I, irm_l, irm_L}
+
+   The set of "num" is defined as:
+   -------------------------------
+   num   = {irm_f, irm_d, irm_c, irm_C, irm_h, irm_H,
+            irm_i, irm_I, irm_l, irm_L}
+            = {float || int}
+
+   The set of "data" is defined as:
+   -------------------------------
+   data  = {irm_f, irm_d, irm_c, irm_C, irm_h, irm_H,
+            irm_i, irm_I, irm_l, irm_L, irm_p}
+            = {num || irm_p}
+
+   The set of "datab" is defined as:
+   ---------------------------------
+   datab = {irm_f, irm_d, irm_c, irm_C, irm_h, irm_H,
+            irm_i, irm_I, irm_l, irm_L, irm_p, irm_b, irm_B}
+            = {data || irm_b || irm_B}
+
+   The set of "dataM" is defined as:
+   ---------------------------------
+   dataM = {irm_f, irm_d, irm_c, irm_C, irm_h, irm_H, irm_i,
+            irm_I, irm_l, irm_L, irm_p, irm_M}
+            = {data || irm_M}
+*/
+
+int
+mode_is_signed (ir_mode *mode)
+{
+   int res;
+   unsigned fsigned;
+   fsigned = get_fsigned_of_mode (mode);
+   if (fsigned == 1) {
+     res = 1;
+    }
+   else {
+     res = 0;
+   }
+   return res;
+}
+
+int
+mode_is_float (ir_mode *mode)
+{
+   int res;
+   unsigned ffloat;
+   ffloat = get_ffloat_of_mode (mode);
+   if (ffloat == 1) {
+      res = 1;
+    }
+   else {
+     res = 0;
+   }
+   return res;
+}
+
+
+int
+mode_is_int (ir_mode *mode)
+{
+   int res;
+   modecode code;
+   code = get_modecode_of_mode (mode);
+   if ((code >= irm_c) &&  (code <= irm_L)) {
+      res = 1;
+    }
+   else {
+     res = 0;
+   }
+   return res;
+}
+
+
+int
+mode_is_num (ir_mode *mode)
+{
+  int res;
+  if (mode_is_int (mode) || mode_is_float (mode)) {
+    res = 1;
+  }
+  else {
+    res = 0;
+  }
+  return res;
+}
+
+int
+mode_is_data (ir_mode *mode)
+{
+  int res;
+  modecode code;
+  code = get_modecode_of_mode (mode);
+  if (mode_is_num (mode) || code == irm_p) {
+    res = 1;
+  }
+  else {
+    res = 0;
+  }
+  return res;
+}
+
+int
+mode_is_datab (ir_mode *mode)
+{
+  int res;
+  modecode code;
+  code = get_modecode_of_mode (mode);
+  if (mode_is_data (mode) || code == irm_b || code == irm_B) {
+    res = 1;
+  }
+  else {
+    res = 0;
+  }
+  return res;
+}
+
+int
+mode_is_dataM (ir_mode *mode)
+{
+  int res;
+  modecode code;
+  code = get_modecode_of_mode (mode);
+  if (mode_is_data (mode) || code == irm_M) {
+    res = 1;
+  }
+  else {
+    res = 0;
+  }
+  return res;
+}
diff --git a/ir/ir/irmode.h b/ir/ir/irmode.h
new file mode 100644 (file)
index 0000000..24befb3
--- /dev/null
@@ -0,0 +1,107 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer
+**
+*/
+
+# ifndef _IRMODE_H_
+# define _IRMODE_H_
+
+#include "ident.h"
+
+# define target_bits 8
+
+#define NUM_MODES 20
+
+typedef enum { /* irm is short for `ir mode' */
+  irm_T,                        // former irm_N
+  irm_f, irm_d, /* irm_e, */
+  irm_c, irm_C, irm_h, irm_H, irm_i, irm_I, irm_l, irm_L,
+  irm_B, irm_b,
+  irm_p,
+  irm_s, irm_S,
+  irm_X, irm_M, irm_R, irm_Z,
+  irm_max
+  /*  according to tech report 1999-44:
+  irm_BB, irm_X,                 // basic block, execution
+  irm_F, irm_D, irm_E,           // float, double, extended
+  irm_B, irm_Bu, irm_H, irm_Hu, irm_I, irm_Iu, irm_L, irm_Lu,
+                                 // byte, short, int, long
+  irm_C,                         // character
+  irm_P,                         // pointer
+  irm_b,                         // internal boolean
+  irm_M,                         // memory
+  irm_T,                         // tuple
+  irm_max */
+} modecode;
+
+typedef struct {
+  modecode code;
+  ident *name;
+  int    size;
+  int    ld_align; /* ld means log2 */
+  struct tarval *min;
+  struct tarval *max;
+  struct tarval *null;
+  unsigned fsigned:1;
+  unsigned ffloat:1;
+} ir_mode;
+
+extern ir_mode *mode_T; /* tuple (none) */
+extern ir_mode *mode_f; /* signed float */
+extern ir_mode *mode_d; /* signed double */
+/* extern ir_mode *mode_e; * signed extended */
+extern ir_mode *mode_c; /* signed byte (former char) */
+extern ir_mode *mode_C; /* unsigned byte (former char) */
+extern ir_mode *mode_h; /* signed short integer */
+extern ir_mode *mode_H; /* unsigened short integer */
+extern ir_mode *mode_i; /* signed integer */
+extern ir_mode *mode_I; /* unsigned integer */
+extern ir_mode *mode_l; /* signed long integer */
+extern ir_mode *mode_L; /* unsigned long integer */
+extern ir_mode *mode_B; /* bits */             // oblivious
+/* extern ir_mode *mode_c;  * char */
+extern ir_mode *mode_p; /* pointer */
+extern ir_mode *mode_b; /* internal boolean */
+extern ir_mode *mode_s;                        // oblivious
+extern ir_mode *mode_S;                        // oblivious
+extern ir_mode *mode_X; /* execution */
+extern ir_mode *mode_M; /* memory */
+extern ir_mode *mode_R; /* block */
+extern ir_mode *mode_Z; /* infinit integers */ // oblivious
+extern ir_mode *mode_T; /* tuple (none) */
+
+void init_mode (void);
+
+modecode get_modecode_of_mode (ir_mode *mode);
+// void set_modecode_of_mode (ir_mode *mode, modecode code);
+ident *get_ident_of_mode (ir_mode *mode);
+ident *get_mode_ident (ir_mode *mode);
+
+// void set_ident_of_mode (ir_mode *mode, ident *name);
+int get_size_of_mode (ir_mode *mode);
+// void set_size_of_mode (ir_mode *mode, int size);
+int get_ld_align_of_mode (ir_mode *mode);
+// void set_ld_align_of_mode (ir_mode *mode, int ld_align);
+struct tarval *get_min_of_mode (ir_mode *mode);
+// void set_min_of_mode (ir_mode *mode, struct tarval *min);
+struct tarval *get_max_of_mode (ir_mode *mode);
+// void set_max_of_mode (ir_mode *mode, struct tarval *max);
+struct tarval *get_null_of_mode (ir_mode *mode);
+// void set_null_of_mode (ir_mode *mode, struct tarval *null);
+unsigned get_fsigned_of_mode (ir_mode *mode);
+// void set_fsigned_of_mode (ir_mode *mode, unsigned fsigned);
+unsigned get_ffloat_of_mode (ir_mode *mode);
+// void set_ffloat_of_mode (ir_mode *mode, unsigned ffloat);
+
+int mode_is_signed (ir_mode *mode);
+int mode_is_float (ir_mode *mode);
+int mode_is_int (ir_mode *mode);
+# define is_chilCHIL(m) ((m) <= irm_L && (m) >= irm_c) // old
+int mode_is_num (ir_mode *mode);
+int mode_is_data (ir_mode *mode);
+int mode_is_datab (ir_mode *mode);
+int mode_is_dataM (ir_mode *mode);
+
+# endif /* _IRMODE_H_ */
diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c
new file mode 100644 (file)
index 0000000..c593587
--- /dev/null
@@ -0,0 +1,1637 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer, Goetz Lindenmaier
+**
+*/
+
+#include "irnode.h"
+#include "array.h"
+
+static char *pnc_name_arr [] = {"False", "Eq", "Lt", "Le",
+                               "Gt", "Ge", "Lg", "Leg", "Uo",
+                               "Ue", "Ul", "Ule", "Ug", "Uge",
+                               "Ne", "True" };
+
+inline char *get_pnc_string(int pnc) {
+  return pnc_name_arr[pnc];
+}
+
+
+int
+get_negated_pnc(int pnc) {
+  switch (pnc) {
+  case False: return True;  break;
+  case Eq:    return Ne;    break;
+  case Lt:    return Uge;   break;
+  case Le:    return Ug;    break;
+  case Gt:    return Ule;   break;
+  case Ge:    return Ul;    break;
+  case Lg:    return Ue;    break;
+  case Leg:   return Uo;    break;
+  case Uo:    return Leg;   break;
+  case Ue:    return Lg;    break;
+  case Ul:    return Ge;    break;
+  case Ule:   return Gt;    break;
+  case Ug:    return Le;    break;
+  case Uge:   return Lt;    break;
+  case Ne:    return Eq;    break;
+  case True:  return False; break;
+  }
+  return 99; /* to shut up gcc */
+}
+
+static char *pns_name_arr [] = {"initial_exec", "global_store",
+                               "frame_base", "globals", "args"};
+
+static char *symconst_name_arr [] = {"type_tag", "size", "linkage_ptr_info"};
+
+
+
+void
+init_irnode (void)
+{
+}
+
+#if 0 /* I didn't manage to place this here as it causes cyclic inclusion
+         of header files/a cyclic dependency between ir_graph and ir_node. */
+/* irnode constructor                                             */
+/* create a new irnode in irg, with an op, mode, arity and        */
+/* some incoming irnodes                                          */
+/* this constructor is used in every specified irnode constructor */
+inline ir_node *
+new_ir_node (ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mode,
+            int arity, ir_node **in)
+{
+  ir_node *res;
+  int node_size = offsetof (ir_node, attr) +  op->attr_size;
+
+  res = (ir_node *) obstack_alloc (irg->obst, node_size);
+
+  res->kind = k_ir_node;
+  res->op = op;
+  res->mode = mode;
+  res->visit = 0;
+  res->link = NULL;
+  if (arity < 0) {
+    res->in = NEW_ARR_F (ir_node *, 1);
+  } else {
+    res->in = NEW_ARR_D (ir_node *, irg->obst, (arity+1));
+    memcpy (&res->in[1], in, sizeof (ir_node *) * arity);
+  }
+  res->in[0] = block;
+  return res;
+}
+#endif
+
+
+/* IR-Nodes with attributes */
+int
+ir_node_print (XP_PAR1, const xprintf_info *info ATTRIBUTE((unused)), XP_PARN)
+{
+  int printed = 0;
+  ir_node *np = XP_GETARG (ir_node *, 0);
+
+  if (!np) {
+    XPS ("<null ir_node>");
+    return printed;
+  }
+
+  XPF1 ("%I", get_irn_op(np)->name);
+
+  switch (get_irn_opcode (np)) {       /* node label */
+  case iro_Const:
+    XPF1 ("%I", get_irn_mode(np)->name);
+    XPS (" : ");
+    XPF1 ("%v", get_irn_const_attr);
+    break;
+  case iro_Proj:
+    if (get_irn_modecode (np) == irm_b) {
+      XPC (" ");
+      XP (pnc_name_arr[get_irn_proj_attr(np)]);
+    } else if (get_irn_opcode (get_irn_in (np)[1]) == iro_Start) {
+      XPC (" ");
+      XP (pns_name_arr[get_irn_proj_attr(np)]);
+    } else {
+      XPF1 ("%I", get_irn_mode(np)->name);
+      XPC (" ");
+      XPF1 ("%d", get_irn_proj_attr(np));
+    }
+    break;
+  case iro_SymConst:
+    XPF1 ("%I", get_irn_mode(np)->name);
+    XPC  (" ");
+    XP   (symconst_name_arr[get_irn_symconst_attr(np).num]);
+    XPF1 (" %#N", get_class_ident((type_class *)get_SymConst_type(np)));
+    break;
+  case iro_Start:              /* don't dump mode of these */
+  case iro_Cond:
+  case iro_Block:
+  case iro_Call:
+  case iro_Jmp:
+  case iro_Return:
+  case iro_End:
+    break;
+  default:
+    XPF1 ("%I", get_irn_mode(np)->name);
+  }
+
+  return printed;
+}
+
+
+/** getting some parameters from ir_nodes **/
+
+/* returns the number of predecessors without the block predecessor. */
+inline int
+get_irn_arity (ir_node *node)
+{
+  // printf("called for node %s\n", ID_TO_STR(node->op->name));
+  // if (get_irn_opcode(node) == iro_Block) return (ARR_LEN((node)->in));
+  return (ARR_LEN((node)->in)-1);
+}
+
+/* returns the array with ins */
+inline ir_node **
+get_irn_in (ir_node *node)
+{
+  assert (node);
+  return ((node)->in);
+}
+
+/* to iterate through the predecessors without touching the array */
+/* To iterate over the operands iterate from 0 to i < get_irn_arity(),
+   to iterate includind the Block predecessor iterate from i = -1 to
+   i < get_irn_arity.
+   Don't know how to iterate if it is a block ?? */
+inline ir_node *
+get_irn_n (ir_node *node, int n)
+{
+  assert (node);
+  // assert (get_irn_arity (node) > n);
+  return skip_nop(node->in[n+1]);
+}
+
+inline void
+set_irn_n (ir_node *node, int n, ir_node *in)
+{
+  assert (node);
+  assert (get_irn_arity (node) > n);
+  node->in[n+1] = in;
+}
+
+inline ir_mode *
+get_irn_mode (ir_node *node)
+{
+  assert (node);
+  return node->mode;
+}
+
+inline modecode
+get_irn_modecode (ir_node *node)
+{
+  assert (node);
+  return node->mode->code;
+}
+
+inline ir_op *
+get_irn_op (ir_node *node)
+{
+  assert (node);
+  return node->op;
+}
+
+/* should be private to the library: */
+inline void
+set_irn_op (ir_node *node, ir_op *op)
+{
+  assert (node);
+  node->op = op;
+}
+
+inline opcode
+get_irn_opcode (ir_node *node)
+{
+  assert (node);
+  return node->op->code;
+}
+
+inline void
+set_irn_link (ir_node *node, ir_node *link) {
+  assert (node);
+  node->link = link;
+}
+
+inline ir_node *
+get_irn_link (ir_node *node) {
+  assert (node);
+  return node->link;
+}
+
+inline tarval *
+get_irn_const_attr (ir_node *node)
+{
+  assert (node->op == op_Const);
+  return node->attr.con;
+}
+
+inline long
+get_irn_proj_attr (ir_node *node)
+{
+  assert (node->op == op_Proj);
+  return node->attr.proj;
+}
+
+inline alloc_attr
+get_irn_alloc_attr (ir_node *node)
+{
+  assert (node->op == op_Alloc);
+  return node->attr.a;
+}
+
+inline type *
+get_irn_free_attr     (ir_node *node)
+{
+  assert (node->op == op_Free);
+  return node->attr.f;
+}
+
+inline symconst_attr
+get_irn_symconst_attr (ir_node *node)
+{
+  assert (node->op == op_SymConst);
+  return node->attr.i;
+}
+
+inline type_method *
+get_irn_call_attr (ir_node *node)
+{
+  assert (node->op == op_Call);
+  return node->attr.call;
+}
+
+inline sel_attr
+get_irn_sel_attr (ir_node *node)
+{
+  assert (node->op == op_Sel);
+  return node->attr.s;
+}
+
+inline int
+get_irn_phi_attr (ir_node *node)
+{
+  assert (node->op == op_Phi);
+  return node->attr.phi0_pos;
+}
+
+inline block_attr
+get_irn_block_attr (ir_node *node)
+{
+  assert (node->op == op_Block);
+  return node->attr.block;
+}
+
+/** manipulate fields of individual nodes **/
+
+/* this works for all except Block */
+ir_node *
+get_nodes_Block (ir_node *node) {
+  assert (!(node->op == op_Block));
+  return get_irn_n(node, -1);
+}
+
+inline void
+set_nodes_Block (ir_node *node, ir_node *block) {
+  assert (!(node->op == op_Block));
+  set_irn_n(node, -1, block);
+}
+
+inline int
+get_Block_n_cfgpreds (ir_node *node) {
+  assert ((node->op == op_Block));
+  return (get_irn_arity(node));
+}
+
+/*
+inline void
+set_Block_n_cfgpreds (ir_node *node, int n_preds) {
+  assert ((node->op == op_Block));
+}
+*/
+
+inline ir_node *
+get_Block_cfgpred (ir_node *node, int pos) {
+  assert (node->op == op_Block);
+  return get_irn_n(node, pos);
+}
+
+inline void
+set_Block_cfgpred (ir_node *node, int pos, ir_node *pred) {
+  assert (node->op == op_Block);
+  set_irn_n(node, pos, pred);
+}
+
+inline bool
+get_Block_matured (ir_node *node) {
+  assert (node->op == op_Block);
+  return node->attr.block.matured;
+}
+
+inline void
+set_Block_matured (ir_node *node, bool matured) {
+  assert (node->op == op_Block);
+  node->attr.block.matured = matured;
+}
+inline unsigned long
+get_Block_block_visit (ir_node *node) {
+  assert (node->op == op_Block);
+  return node->attr.block.block_visit;
+}
+
+inline void
+set_Block_block_visit (ir_node *node, unsigned long visit) {
+  assert (node->op == op_Block);
+  node->attr.block.block_visit = visit;
+}
+
+inline ir_node *
+get_Block_graph_arr (ir_node *node, int pos) {
+  assert (node->op == op_Block);
+  return node->attr.block.graph_arr[pos+1];
+}
+
+inline void
+set_Block_graph_arr (ir_node *node, int pos, ir_node *value) {
+  assert (node->op == op_Block);
+  node->attr.block.graph_arr[pos+1] = value;
+}
+
+inline ir_node *
+get_Cond_selector (ir_node *node) {
+  assert (node->op == op_Cond);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Cond_selector (ir_node *node, ir_node *selector) {
+  assert (node->op == op_Cond);
+  set_irn_n(node, 0, selector);
+}
+
+inline ir_node *
+get_Return_mem (ir_node *node) {
+  assert (node->op == op_Cond);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Return_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Return);
+  set_irn_n(node, 0, mem);
+}
+
+inline int
+get_Return_n_res (ir_node *node) {
+  assert (node->op == op_Return);
+  return (get_irn_arity(node) - 1);
+}
+
+/*
+inline void
+set_Return_n_res (ir_node *node, int results) {
+  assert (node->op == op_Return);
+}
+*/
+
+inline ir_node *
+get_Return_res (ir_node *node, int pos) {
+  assert (node->op == op_Return);
+  return get_irn_n(node, pos+1);
+}
+
+inline void
+set_Return_res (ir_node *node, int pos, ir_node *res){
+  assert (node->op == op_Raise);
+  set_irn_n(node, pos+1, res);
+}
+
+inline ir_node *
+get_Raise_mem (ir_node *node) {
+  assert (node->op == op_Return);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Raise_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Raise);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Raise_exo_ptr (ir_node *node) {
+  assert (node->op == op_Raise);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Raise_exo_ptr (ir_node *node, ir_node *exo_ptr) {
+  assert (node->op == op_Raise);
+  set_irn_n(node, 1, exo_ptr);
+}
+
+inline tarval *get_Const_tarval (ir_node *node) {
+  assert (node->op == op_Const);
+  return get_irn_const_attr(node);
+}
+
+inline void
+set_Const_tarval (ir_node *node, tarval *con) {
+  assert (node->op == op_Const);
+  node->attr.con = con;
+}
+
+inline symconst_kind
+get_SymConst_kind (ir_node *node) {
+  assert (node->op == op_SymConst);
+  return node->attr.i.num;
+}
+
+inline void
+set_SymConst_kind (ir_node *node, symconst_kind num) {
+  assert (node->op == op_SymConst);
+  node->attr.i.num = num;
+}
+
+inline type *
+get_SymConst_type (ir_node *node) {
+  assert (   (node->op == op_SymConst)
+          && (   get_SymConst_kind(node) == type_tag
+              || get_SymConst_kind(node) == size));
+  return node->attr.i.tori.typ;
+}
+
+inline void
+set_SymConst_type (ir_node *node, type *type) {
+  assert (   (node->op == op_SymConst)
+          && (   get_SymConst_kind(node) == type_tag
+              || get_SymConst_kind(node) == size));
+  node->attr.i.tori.typ = type;
+}
+
+inline ident *
+get_SymConst_ptrinfo (ir_node *node) {
+  assert (   (node->op == op_SymConst)
+          && (get_SymConst_kind(node) == linkage_ptr_info));
+  return node->attr.i.tori.ptrinfo;
+
+
+}
+
+inline void
+set_SymConst_ptrinfo (ir_node *node, ident *ptrinfo) {
+  assert (   (node->op == op_SymConst)
+          && (get_SymConst_kind(node) == linkage_ptr_info));
+  node->attr.i.tori.ptrinfo = ptrinfo;
+}
+
+inline ir_node *
+get_Sel_mem (ir_node *node) {
+  assert (node->op == op_Sel);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Sel_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Sel);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Sel_ptr (ir_node *node) {
+  assert (node->op == op_Sel);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Sel_ptr (ir_node *node, ir_node *ptr) {
+  assert (node->op == op_Sel);
+  set_irn_n(node, 1, ptr);
+}
+
+inline int
+get_Sel_n_index (ir_node *node) {
+  assert (node->op == op_Sel);
+  return (get_irn_arity(node) - 2);
+}
+
+/*
+inline void
+set_Sel_n_index (ir_node *node, int n_index) {
+  assert (node->op == op_Sel);
+}
+*/
+
+inline ir_node *
+get_Sel_index (ir_node *node, int pos) {
+  assert (node->op == op_Sel);
+  return get_irn_n(node, pos+2);
+}
+
+inline void
+set_Sel_index (ir_node *node, int pos, ir_node *index) {
+  assert (node->op == op_Sel);
+  set_irn_n(node, pos+2, index);
+}
+
+inline entity *
+get_Sel_entity (ir_node *node) {
+  assert (node->op == op_Sel);
+  return node->attr.s.ent;
+}
+
+inline void
+set_Sel_entity (ir_node *node, entity *ent) {
+  assert (node->op == op_Sel);
+  node->attr.s.ent = ent;
+}
+
+inline linkage_type *
+get_Sel_linkage_type (ir_node *node) {
+  assert (node->op == op_Sel);
+  return node->attr.s.ltyp;
+}
+
+inline void
+set_Sel_linkage_type (ir_node *node, linkage_type *lt) {
+  assert (node->op == op_Sel);
+  node->attr.s.ltyp = lt;
+}
+
+inline ir_node *
+get_Call_mem (ir_node *node) {
+  assert (node->op == op_Call);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Call_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Call);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Call_ptr (ir_node *node) {
+  assert (node->op == op_Call);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Call_ptr (ir_node *node, ir_node *ptr) {
+  assert (node->op == op_Call);
+  set_irn_n(node, 1, ptr);
+}
+
+inline int
+get_Call_arity (ir_node *node) {
+  assert (node->op == op_Call);
+  return (get_irn_arity(node) - 2);
+}
+
+/* inline void
+set_Call_arity (ir_node *node, ir_node *arity) {
+  assert (node->op == op_Call);
+}
+*/
+
+inline ir_node *
+get_Call_param (ir_node *node, int pos) {
+  assert (node->op == op_Call);
+  return get_irn_n(node, pos+1);
+}
+
+inline void
+set_Call_param (ir_node *node, int pos, ir_node *param) {
+  assert (node->op == op_Call);
+  set_irn_n(node, pos+1, param);
+}
+
+inline type_method *
+get_Call_type (ir_node *node) {
+  assert (node->op == op_Call);
+  return node->attr.call;
+}
+
+inline void
+set_Call_type (ir_node *node, type_method *type) {
+  assert (node->op == op_Call);
+  node->attr.call = type;
+}
+
+/* For unary and binary arithmetic operations the access to the
+   operands can be factored out.  Left is the first, right the
+   second arithmetic value  as listed in tech report 0999-33.
+   unops are: Minus, Abs, Not, Conv
+   binops are: Add, Sub, Mul, Quot, DivMod, Div, Mod, And, Or, Eor, Shl,
+   Shr, Shrs, Rotate, Cmp */
+
+int
+is_unop (ir_node *node) {
+  return ( node->op == op_Minus ||
+           node->op == op_Abs  ||
+          node->op == op_Not  ||
+           node->op == op_Conv );
+}
+
+inline ir_node *
+get_unop_op (ir_node *node) {
+  assert ( node->op == op_Minus ||
+           node->op == op_Abs  ||
+           node->op == op_Not  ||
+           node->op == op_Conv );
+  switch (get_irn_opcode (node)) {
+    case iro_Minus: return get_Minus_op(node); break;
+    case iro_Abs:   return get_Abs_op(node);   break;
+    case iro_Not:   return get_Not_op(node);   break;
+    case iro_Conv:  return get_Conv_op(node);  break;
+    default: return NULL;
+  }
+}
+
+inline void
+set_unop_op (ir_node *node, ir_node *op) {
+    assert (node->op == op_Minus ||
+           node->op == op_Abs   ||
+           node->op == op_Not   ||
+           node->op == op_Conv    );
+    switch (get_irn_opcode (node)) {
+    case iro_Minus:   set_Minus_op(node, op); break;
+    case iro_Abs:     set_Abs_op(node, op);   break;
+    case iro_Not:     set_Not_op(node, op);   break;
+    case iro_Conv:    set_Conv_op(node, op);  break;
+    default:  ;
+    }
+
+}
+
+int
+is_binop (ir_node *node) {
+  return (node->op == op_Add    ||
+          node->op == op_Sub    ||
+          node->op == op_Mul    ||
+          node->op == op_Quot   ||
+          node->op == op_DivMod ||
+          node->op == op_Div    ||
+          node->op == op_Mod    ||
+          node->op == op_And    ||
+          node->op == op_Or     ||
+          node->op == op_Eor    ||
+          node->op == op_Shl    ||
+          node->op == op_Shr    ||
+          node->op == op_Shrs   ||
+         node->op == op_Rot    ||
+          node->op == op_Cmp      );
+}
+
+inline ir_node *
+get_binop_left (ir_node *node) {
+  assert (node->op == op_Add    ||
+          node->op == op_Sub    ||
+          node->op == op_Mul    ||
+          node->op == op_Quot   ||
+          node->op == op_DivMod ||
+          node->op == op_Div    ||
+          node->op == op_Mod    ||
+          node->op == op_And    ||
+          node->op == op_Or     ||
+          node->op == op_Eor    ||
+          node->op == op_Shl    ||
+          node->op == op_Shr    ||
+          node->op == op_Shrs   ||
+         node->op == op_Rot    ||
+          node->op == op_Cmp      );
+
+    switch (get_irn_opcode (node)) {
+      case iro_Add   :     return get_Add_left(node);  break;
+      case iro_Sub   :     return get_Sub_left(node);  break;
+      case iro_Mul   :     return get_Mul_left(node);  break;
+      case iro_Quot  :     return get_Quot_left(node); break;
+      case iro_DivMod:     return get_DivMod_left(node);  break;
+      case iro_Div   :     return get_Div_left(node);  break;
+      case iro_Mod   :     return get_Mod_left(node);  break;
+      case iro_And   :     return get_And_left(node);  break;
+      case iro_Or    :     return get_Or_left(node);   break;
+      case iro_Eor   :     return get_Eor_left(node);  break;
+      case iro_Shl   :     return get_Shl_left(node);  break;
+      case iro_Shr   :     return get_Shr_left(node);  break;
+      case iro_Shrs  :     return get_Shrs_left(node); break;
+      case iro_Rot   :     return get_Rot_left(node);  break;
+      case iro_Cmp   :     return get_Cmp_left(node);  break;
+    default:  return NULL;
+  };
+}
+
+inline void
+set_binop_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Add    ||
+          node->op == op_Sub    ||
+          node->op == op_Mul    ||
+          node->op == op_Quot   ||
+          node->op == op_DivMod ||
+          node->op == op_Div    ||
+          node->op == op_Mod    ||
+          node->op == op_And    ||
+          node->op == op_Or     ||
+          node->op == op_Eor    ||
+          node->op == op_Shl    ||
+          node->op == op_Shr    ||
+         node->op == op_Shrs   ||
+         node->op == op_Rot    ||
+          node->op == op_Cmp      );
+
+    switch (get_irn_opcode (node)) {
+      case iro_Add   :     set_Add_left(node, left);  break;
+      case iro_Sub   :     set_Sub_left(node, left);  break;
+      case iro_Mul   :     set_Mul_left(node, left);  break;
+      case iro_Quot  :     set_Quot_left(node, left); break;
+      case iro_DivMod:     set_DivMod_left(node, left);  break;
+      case iro_Div   :     set_Div_left(node, left);  break;
+      case iro_Mod   :     set_Mod_left(node, left);  break;
+      case iro_And   :     set_And_left(node, left);  break;
+      case iro_Or    :     set_Or_left(node, left);   break;
+      case iro_Eor   :     set_Eor_left(node, left);  break;
+      case iro_Shl   :     set_Shl_left(node, left);  break;
+      case iro_Shr   :     set_Shr_left(node, left);  break;
+      case iro_Shrs  :     set_Shrs_left(node, left); break;
+      case iro_Rot   :     set_Rot_left(node, left);  break;
+      case iro_Cmp   :     set_Cmp_left(node, left);  break;
+    default:  ;
+  };
+}
+
+inline ir_node *
+get_binop_right (ir_node *node) {
+  assert (node->op == op_Add    ||
+          node->op == op_Sub    ||
+          node->op == op_Mul    ||
+          node->op == op_Quot   ||
+          node->op == op_DivMod ||
+          node->op == op_Div    ||
+          node->op == op_Mod    ||
+          node->op == op_And    ||
+          node->op == op_Or     ||
+          node->op == op_Eor    ||
+          node->op == op_Shl    ||
+          node->op == op_Shr    ||
+          node->op == op_Shrs   ||
+          node->op == op_Rot    ||
+          node->op == op_Cmp      );
+
+    switch (get_irn_opcode (node)) {
+      case iro_Add   :     return get_Add_right(node);  break;
+      case iro_Sub   :     return get_Sub_right(node);  break;
+      case iro_Mul   :     return get_Mul_right(node);  break;
+      case iro_Quot  :     return get_Quot_right(node); break;
+      case iro_DivMod:     return get_DivMod_right(node);  break;
+      case iro_Div   :     return get_Div_right(node);  break;
+      case iro_Mod   :     return get_Mod_right(node);  break;
+      case iro_And   :     return get_And_right(node);  break;
+      case iro_Or    :     return get_Or_right(node);   break;
+      case iro_Eor   :     return get_Eor_right(node);  break;
+      case iro_Shl   :     return get_Shl_right(node);  break;
+      case iro_Shr   :     return get_Shr_right(node);  break;
+      case iro_Shrs  :     return get_Shrs_right(node); break;
+      case iro_Rot   :     return get_Rot_right(node);  break;
+      case iro_Cmp   :     return get_Cmp_right(node);  break;
+    default:  return NULL;
+  };
+}
+
+inline void
+set_binop_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Add    ||
+          node->op == op_Sub    ||
+          node->op == op_Mul    ||
+          node->op == op_Quot   ||
+          node->op == op_DivMod ||
+          node->op == op_Div    ||
+          node->op == op_Mod    ||
+          node->op == op_And    ||
+          node->op == op_Or     ||
+          node->op == op_Eor    ||
+          node->op == op_Shl    ||
+          node->op == op_Shr    ||
+          node->op == op_Shrs   ||
+          node->op == op_Rot    ||
+          node->op == op_Cmp      );
+
+    switch (get_irn_opcode (node)) {
+      case iro_Add   :     set_Add_right(node, right);  break;
+      case iro_Sub   :     set_Sub_right(node, right);  break;
+      case iro_Mul   :     set_Mul_right(node, right);  break;
+      case iro_Quot  :     set_Quot_right(node, right); break;
+      case iro_DivMod:     set_DivMod_right(node, right);  break;
+      case iro_Div   :     set_Div_right(node, right);  break;
+      case iro_Mod   :     set_Mod_right(node, right);  break;
+      case iro_And   :     set_And_right(node, right);  break;
+      case iro_Or    :     set_Or_right(node, right);   break;
+      case iro_Eor   :     set_Eor_right(node, right);  break;
+      case iro_Shl   :     set_Shl_right(node, right);  break;
+      case iro_Shr   :     set_Shr_right(node, right);  break;
+      case iro_Shrs  :     set_Shrs_right(node, right); break;
+      case iro_Rot   :     set_Rot_right(node, right);  break;
+      case iro_Cmp   :     set_Cmp_right(node, right);  break;
+    default: ;
+  };
+}
+
+inline ir_node *
+get_Add_left (ir_node *node) {
+  assert (node->op == op_Add);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Add_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Add);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Add_right (ir_node *node) {
+  assert (node->op == op_Add);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Add_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Add);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Sub_left (ir_node *node) {
+  assert (node->op == op_Sub);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Sub_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Sub);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Sub_right (ir_node *node) {
+  assert (node->op == op_Sub);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Sub_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Sub);
+  set_irn_n(node, 1, right);
+}
+
+
+inline ir_node *
+get_Minus_op (ir_node *node) {
+  assert (node->op == op_Minus);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Minus_op (ir_node *node, ir_node *op) {
+  assert (node->op == op_Minus);
+  set_irn_n(node, 0, op);
+}
+
+
+inline ir_node *
+get_Mul_left (ir_node *node) {
+  assert (node->op == op_Mul);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Mul_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Mul);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Mul_right (ir_node *node) {
+  assert (node->op == op_Mul);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Mul_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Mul);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Quot_left (ir_node *node) {
+  assert (node->op == op_Quot);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Quot_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Quot);
+  set_irn_n(node, 1, left);
+}
+
+inline ir_node *
+get_Quot_right (ir_node *node) {
+  assert (node->op == op_Quot);
+  return get_irn_n(node, 2);
+}
+
+inline void
+set_Quot_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Quot);
+  set_irn_n(node, 2, right);
+}
+
+inline ir_node *
+get_Quot_mem (ir_node *node) {
+  assert (node->op == op_Quot);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Quot_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Quot);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_DivMod_left (ir_node *node) {
+  assert (node->op == op_DivMod);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_DivMod_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_DivMod);
+  set_irn_n(node, 1, left);
+}
+
+inline ir_node *
+get_DivMod_right (ir_node *node) {
+  assert (node->op == op_DivMod);
+  return get_irn_n(node, 2);
+}
+
+inline void
+set_DivMod_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_DivMod);
+  set_irn_n(node, 2, right);
+}
+
+inline ir_node *
+get_DivMod_mem (ir_node *node) {
+  assert (node->op == op_DivMod);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_DivMod_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_DivMod);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Div_left (ir_node *node) {
+  assert (node->op == op_Div);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Div_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Div);
+  set_irn_n(node, 1, left);
+}
+
+inline ir_node *
+get_Div_right (ir_node *node) {
+  assert (node->op == op_Div);
+  return get_irn_n(node, 2);
+}
+
+inline void
+set_Div_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Div);
+  set_irn_n(node, 2, right);
+}
+
+inline ir_node *
+get_Div_mem (ir_node *node) {
+  assert (node->op == op_Div);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Div_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Div);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Mod_left (ir_node *node) {
+  assert (node->op == op_Mod);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Mod_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Mod);
+  set_irn_n(node, 1, left);
+}
+
+inline ir_node *
+get_Mod_right (ir_node *node) {
+  assert (node->op == op_Mod);
+  return get_irn_n(node, 2);
+}
+
+inline void
+set_Mod_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Mod);
+  set_irn_n(node, 2, right);
+}
+
+inline ir_node *
+get_Mod_mem (ir_node *node) {
+  assert (node->op == op_Mod);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Mod_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Mod);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Abs_op (ir_node *node) {
+  assert (node->op == op_Abs);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Abs_op (ir_node *node, ir_node *op) {
+  assert (node->op == op_Abs);
+  set_irn_n(node, 0, op);
+}
+
+inline ir_node *
+get_And_left (ir_node *node) {
+  assert (node->op == op_And);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_And_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_And);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_And_right (ir_node *node) {
+  assert (node->op == op_And);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_And_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_And);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Or_left (ir_node *node) {
+  assert (node->op == op_Or);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Or_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Or);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Or_right (ir_node *node) {
+  assert (node->op == op_Or);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Or_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Or);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Eor_left (ir_node *node) {
+  assert (node->op == op_Eor);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Eor_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Eor);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Eor_right (ir_node *node) {
+  assert (node->op == op_Eor);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Eor_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Eor);
+  set_irn_n(node, 1, right);
+}
+
+
+inline ir_node *
+get_Not_op (ir_node *node) {
+  assert (node->op == op_Not);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Not_op (ir_node *node, ir_node *op) {
+  assert (node->op == op_Not);
+  set_irn_n(node, 0, op);
+}
+
+
+inline ir_node *
+get_Shl_left (ir_node *node) {
+  assert (node->op == op_Shl);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Shl_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Shl);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Shl_right (ir_node *node) {
+  assert (node->op == op_Shl);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Shl_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Shl);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Shr_left (ir_node *node) {
+  assert (node->op == op_Shr);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Shr_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Shr);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Shr_right (ir_node *node) {
+  assert (node->op == op_Shr);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Shr_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Shr);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Shrs_left (ir_node *node) {
+  assert (node->op == op_Shrs);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Shrs_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Shrs);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Shrs_right (ir_node *node) {
+  assert (node->op == op_Shrs);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Shrs_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Shrs);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Rot_left (ir_node *node) {
+  assert (node->op == op_Rot);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Rot_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Rot);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Rot_right (ir_node *node) {
+  assert (node->op == op_Rot);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Rot_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Rot);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Cmp_left (ir_node *node) {
+  assert (node->op == op_Cmp);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Cmp_left (ir_node *node, ir_node *left) {
+  assert (node->op == op_Cmp);
+  set_irn_n(node, 0, left);
+}
+
+inline ir_node *
+get_Cmp_right (ir_node *node) {
+  assert (node->op == op_Cmp);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Cmp_right (ir_node *node, ir_node *right) {
+  assert (node->op == op_Cmp);
+  set_irn_n(node, 1, right);
+}
+
+inline ir_node *
+get_Conv_op (ir_node *node) {
+  assert (node->op == op_Conv);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Conv_op (ir_node *node, ir_node *op) {
+  assert (node->op == op_Conv);
+  set_irn_n(node, 0, op);
+}
+
+inline int
+get_Phi_n_preds (ir_node *node) {
+  assert (node->op == op_Phi);
+  return (get_irn_arity(node));
+}
+
+/*
+inline void set_Phi_n_preds (ir_node *node, int n_preds) {
+  assert (node->op == op_Phi);
+}
+*/
+
+inline ir_node *
+get_Phi_pred (ir_node *node, int pos) {
+  assert (node->op == op_Phi);
+  return get_irn_n(node, pos);
+}
+
+inline void
+set_Phi_pred (ir_node *node, int pos, ir_node *pred) {
+  assert (node->op == op_Phi);
+  set_irn_n(node, pos, pred);
+}
+
+inline ir_node *
+get_Load_mem (ir_node *node) {
+  assert (node->op == op_Load);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Load_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Load);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Load_ptr (ir_node *node) {
+  assert (node->op == op_Load);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Load_ptr (ir_node *node, ir_node *ptr) {
+  assert (node->op == op_Load);
+  set_irn_n(node, 1, ptr);
+}
+
+inline
+ir_node *
+get_Store_mem (ir_node *node) {
+  assert (node->op == op_Store);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Store_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Store);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Store_ptr (ir_node *node) {
+  assert (node->op == op_Store);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Store_ptr (ir_node *node, ir_node *ptr) {
+  assert (node->op == op_Store);
+  set_irn_n(node, 1, ptr);
+}
+
+inline ir_node *
+get_Store_value (ir_node *node) {
+  assert (node->op == op_Store);
+  return get_irn_n(node, 2);
+}
+
+inline void
+set_Store_value (ir_node *node, ir_node *value) {
+  assert (node->op == op_Store);
+  set_irn_n(node, 2, value);
+}
+
+inline ir_node *
+get_Alloc_mem (ir_node *node) {
+  assert (node->op == op_Alloc);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Alloc_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Alloc);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Alloc_size (ir_node *node) {
+  assert (node->op == op_Alloc);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Allco_size (ir_node *node, ir_node *size) {
+  assert (node->op == op_Alloc);
+  set_irn_n(node, 1, size);
+}
+
+inline type  *
+get_Alloc_type (ir_node *node) {
+  assert (node->op == op_Alloc);
+  return node->attr.a.type;
+}
+
+inline void
+set_Alloc_type (ir_node *node, type *type) {
+  assert (node->op == op_Alloc);
+  node->attr.a.type = type;
+}
+
+inline where_alloc
+get_Alloc_where (ir_node *node) {
+  assert (node->op == op_Alloc);
+  return node->attr.a.where;
+}
+
+inline void
+set_Alloc_where (ir_node *node, where_alloc where) {
+  assert (node->op == op_Alloc);
+  node->attr.a.where = where;
+}
+
+
+inline ir_node *
+get_Free_mem (ir_node *node) {
+  assert (node->op == op_Free);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Free_mem (ir_node *node, ir_node *mem) {
+  assert (node->op == op_Free);
+  set_irn_n(node, 0, mem);
+}
+
+inline ir_node *
+get_Free_ptr (ir_node *node) {
+  assert (node->op == op_Free);
+  return get_irn_n(node, 1);
+}
+
+inline void
+set_Free_ptr (ir_node *node, ir_node *ptr) {
+  assert (node->op == op_Free);
+  set_irn_n(node, 1, ptr);
+}
+
+inline ir_node *
+get_Free_size (ir_node *node) {
+  assert (node->op == op_Free);
+  return get_irn_n(node, 2);
+}
+
+inline void
+set_Free_size (ir_node *node, ir_node *size) {
+  assert (node->op == op_Free);
+  set_irn_n(node, 2, size);
+}
+
+inline type  *
+get_Free_type (ir_node *node) {
+  assert (node->op == op_Free);
+  return node->attr.f;
+}
+
+inline void
+set_Free_type (ir_node *node, type *type) {
+  assert (node->op == op_Free);
+  node->attr.f = type;
+}
+
+inline int
+get_Sync_n_preds (ir_node *node) {
+  assert (node->op == op_Sync);
+  return (get_irn_arity(node));
+}
+
+/*
+inline void
+set_Sync_n_preds (ir_node *node, int n_preds) {
+  assert (node->op == op_Sync);
+}
+*/
+
+inline ir_node *
+get_Sync_pred (ir_node *node, int pos) {
+  assert (node->op == op_Sync);
+  return get_irn_n(node, pos);
+}
+
+inline void
+set_Sync_pred (ir_node *node, int pos, ir_node *pred) {
+  assert (node->op == op_Sync);
+  set_irn_n(node, pos, pred);
+}
+
+inline ir_node *
+get_Proj_pred (ir_node *node) {
+  assert (node->op == op_Proj);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Proj_pred (ir_node *node, ir_node *pred) {
+  assert (node->op == op_Proj);
+  set_irn_n(node, 0, pred);
+}
+
+inline long
+get_Proj_proj (ir_node *node) {
+  assert (node->op == op_Proj);
+  return node->attr.proj;
+}
+
+inline void
+set_Proj_proj (ir_node *node, long proj) {
+  assert (node->op == op_Proj);
+  node->attr.proj = proj;
+}
+
+inline int
+get_Tuple_n_preds (ir_node *node) {
+  assert (node->op == op_Tuple);
+  return (get_irn_arity(node));
+}
+
+/*
+inline void
+set_Tuple_n_preds (ir_node *node, int n_preds) {
+  assert (node->op == op_Tuple);
+}
+*/
+
+inline ir_node *
+get_Tuple_pred (ir_node *node, int pos) {
+  assert (node->op == op_Tuple);
+  return get_irn_n(node, pos);
+}
+
+inline void
+set_Tuple_pred (ir_node *node, int pos, ir_node *pred) {
+  assert (node->op == op_Tuple);
+  set_irn_n(node, pos, pred);
+}
+
+inline ir_node *
+get_Id_pred (ir_node *node) {
+  assert (node->op == op_Id);
+  return get_irn_n(node, 0);
+}
+
+inline void
+set_Id_pred (ir_node *node, ir_node *pred) {
+  assert (node->op == op_Id);
+  set_irn_n(node, 0, pred);
+}
+
+/******************************************************************/
+/*  Auxiliary routines                                            */
+/******************************************************************/
+
+inline ir_node *
+skip_Proj (ir_node *node) {
+  /* don't assert node !!! */
+  if (node && (node->op == op_Proj)) {
+    return get_Proj_pred(node);
+  } else {
+    return node;
+  }
+}
+
+inline ir_node *
+skip_nop (ir_node *node) {
+  /* don't assert node !!! */
+  if (node && (node->op == op_Id)) {
+    return get_Id_pred(node);
+  } else {
+    return node;
+  }
+}
+
+inline int
+is_Bad (ir_node *node) {
+  assert(node);
+  if ((node) && get_irn_opcode(node) == iro_Bad)
+    return 1;
+  return 0;
+}
+
+inline int
+is_no_Block (ir_node *node) {
+  assert(node);
+  return (get_irn_opcode(node) != iro_Block);
+}
+
+/* Returns true if the operation manipulates control flow. */
+int
+is_cfop(ir_node *node) {
+  return (   (get_irn_opcode(node) == iro_Start)
+          || (get_irn_opcode(node) == iro_Jmp)
+          || (get_irn_opcode(node) == iro_Cond)
+          || (get_irn_opcode(node) == iro_Return)
+          || (get_irn_opcode(node) == iro_Raise)
+          || (get_irn_opcode(node) == iro_Bad));
+}
+
+/* Returns true if the operation can change the control flow because
+   of an exception. */
+int
+is_fragile_op(ir_node *node) {
+  return (   (get_irn_opcode(node) == iro_Call)
+          || (get_irn_opcode(node) == iro_Quot)
+          || (get_irn_opcode(node) == iro_DivMod)
+          || (get_irn_opcode(node) == iro_Div)
+          || (get_irn_opcode(node) == iro_Mod)
+          || (get_irn_opcode(node) == iro_Load)
+          || (get_irn_opcode(node) == iro_Store)
+          || (get_irn_opcode(node) == iro_Alloc)
+          || (get_irn_opcode(node) == iro_Bad));
+}
diff --git a/ir/ir/irnode.h b/ir/ir/irnode.h
new file mode 100644 (file)
index 0000000..7ee5e6e
--- /dev/null
@@ -0,0 +1,445 @@
+
+
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** declarations of an ir node
+*/
+
+# ifndef _IRNODE_H_
+# define _IRNODE_H_
+
+# include "entity.h"
+# include "common.h"
+# include "irop.h"
+# include "irmode.h"
+# include "tv.h"
+# include "type.h"
+
+/* projection numbers of compare. */
+enum {
+  False,               /* false */
+  Eq,                  /* equal */
+  Lt,                  /* less */
+  Le,                  /* less or equal */
+  Gt,                  /* greater */
+  Ge,                  /* greater or equal */
+  Lg,                  /* less or greater */
+  Leg,                 /* less, equal or greater = ordered */
+  Uo,                  /* unordered */
+  Ue,                  /* unordered or equal */
+  Ul,                  /* unordered or less */
+  Ule,                 /* unordered, less or equal */
+  Ug,                  /* unordered or greater */
+  Uge,                 /* unordered, greater or equal */
+  Ne,                  /* unordered, less or greater = not equal */
+  True,                        /* true */
+  not_mask = Leg       /* bits to flip to negate comparison */
+} pnc_number;
+
+inline char *
+get_pnc_string(int pnc);
+
+int
+get_negated_pnc(int pnc);
+
+
+/* projection numbers for result of Start node. */
+enum {
+  pns_initial_exec,     /* Projection on an executable, the initial control
+                          flow. */
+  pns_global_store,     /* Projection on the global store */
+  pns_frame_base,       /* Projection on the frame base */
+  pns_globals,          /* Projection on the pointer to the data segment
+                          containing _all_ global entities. */
+  pns_args              /* Projection on all arguments */
+} pns_number;
+
+/* ir node attributes */
+typedef struct {
+  unsigned long block_visit;  /* for the walker that walks over all blocks. */
+  /* Attributes private to construction: */
+  bool matured;               /* if set, all in-nodes of the block are fixed */
+  struct ir_node **graph_arr; /* array to store all parameters */
+} block_attr;
+
+typedef enum {
+  type_tag,          /* The SymConst is a type tag for the given type. */
+  size,              /* The SymConst is the size of the given type. */
+  linkage_ptr_info   /* The SymConst is a symbolic pointer to be filled in
+                       by the linker. */
+} symconst_kind;
+
+typedef union {
+  type *typ;
+  ident *ptrinfo;
+} type_or_id;
+
+typedef struct {
+  type_or_id tori;
+  symconst_kind num;
+} symconst_attr;
+
+typedef enum {
+  static_linkage,       /* entity is used internal and not visible out of this
+                          file/class. */
+  external_linkage,     /* */
+  no_linkage
+} linkage_type;
+
+typedef struct {
+  entity *ent;          /* entity to select */
+  linkage_type *ltyp;   /* linkage type of the entity */
+} sel_attr;
+
+typedef enum {
+  stack_alloc,          /* Alloc allocates the object on the stack. */
+  heap_alloc            /* lloc allocates the object on the heap. */
+} where_alloc;
+
+typedef struct {
+  type *type;           /* Type of the allocated object.  */
+  where_alloc where;    /* stack, heap or other managed part of memory */
+} alloc_attr;
+
+/* Some irnodes just have one attribute, these are stored here,
+   some have more. Their name is 'irnodename_attr' */
+typedef union {
+  block_attr     block; /* For Block: Fields needed to construct it */
+  struct tarval *con;   /* For Const: contains the value of the constant */
+  symconst_attr  i;     /* For SymConst. */
+  sel_attr       s;     /* For Sel. */
+  type_method   *call;  /* For Call: pointer to the type of the method to call */
+  long           proj;  /* For Proj: contains the result position to project */
+  alloc_attr     a;     /* For Alloc. */
+  type          *f;     /* For Free. */
+  int            phi0_pos;  /* For Phi. Used to remember the value defined by
+                              this Phi node.  Needed when the Phi is completed
+                              to call get_r_internal_value to find the
+                              predecessors. If this attribute is set, the Phi
+                              node takes the role of the obsolete Phi0 node,
+                              therefore the name. */
+} attr;
+
+
+/* common structure of an irnode */
+/* if the node has some attributes, they are stored in attr */
+
+typedef struct ir_node {
+  firm_kind kind;          /* distinguishes this node from others */
+  ir_op *op;               /* Opcode of this node. */
+  ir_mode *mode;           /* Mode of this node. */
+  unsigned long visit;     /* visited counter for walks of the graph */
+  struct ir_node **in;     /* array with predecessors / operands */
+  struct ir_node *link;    /* for linking nodes somehow to a list, e.g.
+                              used while construction to link Phi0 nodes and
+                             during optimization to link to nodes that
+                             shall replace a node. */
+  attr attr;               /* attribute of this node. Depends on opcode. */
+                           /* Must be last attribute of struct ir_node. */
+} ir_node;
+
+
+#if 0 /* I didn't manage to place this here as it causes cyclic inclusion
+         of header files/a cyclic dependency between ir_graph and ir_node. */
+/* irnode constructor                                             */
+/* Create a new irnode in irg, with an op, mode, arity and        */
+/* some incoming irnodes.                                         */
+/* If arity is negative, a node with a dynamic array is created.  */
+inline ir_node *new_ir_node (int *irg, ir_node *block, ir_op *op,
+                            ir_mode *mode, int arity, ir_node **in);
+#endif
+
+/* Print IR-Nodes with attributes */
+int ir_node_print (XP_PAR1, const xprintf_info *, XP_PARN);
+
+
+/** manipulate the fields of ir_node **/
+
+/* returns the number of predecessors without the block predecessor: */
+int                  get_irn_arity         (ir_node *node);
+/* returns the array with the ins: */
+inline ir_node     **get_irn_in            (ir_node *node);
+/* to iterate through the predecessors without touching the array. No
+   order of predecessors guaranteed.
+   To iterate over the operands iterate from 0 to i < get_irn_arity(),
+   to iterate includind the Block predecessor iterate from i = -1 to
+   i < get_irn_arity. */
+inline ir_node      *get_irn_n             (ir_node *node, int n);
+inline void          set_irn_n             (ir_node *node, int n, ir_node *in);
+inline ir_mode      *get_irn_mode          (ir_node *node);
+inline modecode      get_irn_modecode      (ir_node *node);
+inline ir_op        *get_irn_op            (ir_node *node);
+/* should be private to the library: */
+inline void          set_irn_op            (ir_node *node, ir_op *op);
+inline opcode        get_irn_opcode        (ir_node *node);
+inline void          set_irn_link          (ir_node *node, ir_node *link);
+inline ir_node      *get_irn_link          (ir_node *node);
+
+
+/** access attributes directly **/
+inline tarval       *get_irn_const_attr    (ir_node *node);
+inline long          get_irn_proj_attr     (ir_node *node);
+inline alloc_attr    get_irn_alloc_attr    (ir_node *node);
+inline type         *get_irn_free_attr     (ir_node *node);
+inline symconst_attr get_irn_symconst_attr (ir_node *node);
+type_method  *get_irn_call_attr     (ir_node *node);
+sel_attr      get_irn_sel_attr      (ir_node *node);
+int           get_irn_phi_attr      (ir_node *node);
+block_attr    get_irn_return_attr   (ir_node *node);
+
+/** manipulate fields of individual nodes **/
+
+/* this works for all except Block */
+inline ir_node *get_nodes_Block (ir_node *node);
+inline void     set_nodes_Block (ir_node *node, ir_node *block);
+
+int             get_Block_n_cfgpreds (ir_node *node);
+/* inline void    set_Block_n_cfgpreds (ir_node *node, int n_preds); */
+inline ir_node *get_Block_cfgpred (ir_node *node, int pos);
+inline void     set_Block_cfgpred (ir_node *node, int pos, ir_node *pred);
+inline bool     get_Block_matured (ir_node *node);
+inline void     set_Block_matured (ir_node *node, bool matured);
+inline bool     get_Block_closed (ir_node *node);
+inline void     set_Block_closed (ir_node *node, bool closed);
+inline unsigned long get_Block_block_visit (ir_node *node);
+inline void     set_Block_block_visit (ir_node *node, unsigned long visit);
+inline ir_node *get_Block_graph_arr (ir_node *node, int pos);
+inline void     set_Block_graph_arr (ir_node *node, int pos, ir_node *value);
+
+inline ir_node *get_Cond_selector (ir_node *node);
+inline void     set_Cond_selector (ir_node *node, ir_node *selector);
+
+inline ir_node *get_Return_mem (ir_node *node);
+inline void     set_Return_mem (ir_node *node, ir_node *mem);
+inline int      get_Return_n_res (ir_node *node);
+/*inline void     set_Return_n_res (ir_node *node, int results); */
+inline ir_node *get_Return_res (ir_node *node, int pos);
+inline void     set_Return_res (ir_node *node, int pos, ir_node *res);
+
+inline ir_node *get_Raise_mem (ir_node *node);
+inline void     set_Raise_mem (ir_node *node, ir_node *mem);
+inline ir_node *get_Raise_exoptr (ir_node *node);  /* PoinTeR to EXception Object */
+inline void     set_Raise_exoptr (ir_node *node, ir_node *exoptr);
+
+inline tarval  *get_Const_tarval (ir_node *node);
+inline void     set_Const_tarval (ir_node *node, tarval *con);
+
+inline symconst_kind get_SymConst_kind (ir_node *node);
+inline void          set_SymConst_kind (ir_node *node, symconst_kind num);
+inline type    *get_SymConst_type (ir_node *node);
+inline void     set_SymConst_type (ir_node *node, type *type);
+inline ident   *get_SymConst_ptrinfo (ir_node *node);
+inline void     set_SymConst_ptrinfo (ir_node *node, ident *ptrinfo);
+
+inline ir_node *get_Sel_mem (ir_node *node);
+inline void     set_Sel_mem (ir_node *node, ir_node *mem);
+inline ir_node *get_Sel_ptr (ir_node *node);  /* ptr to the object to select from */
+inline void     set_Sel_ptr (ir_node *node, ir_node *ptr);
+inline int      get_Sel_n_index (ir_node *node);
+/*inline void     set_Sel_n_index (ir_node *node, int n_index); */
+inline ir_node *get_Sel_index (ir_node *node, int pos);
+inline void     set_Sel_index (ir_node *node, int pos, ir_node *index);
+inline entity  *get_Sel_entity (ir_node *node); /* entity to select */
+inline void     set_Sel_entity (ir_node *node, entity *ent);
+inline linkage_type *get_Sel_linkage_type (ir_node *node);
+inline void     set_Sel_linkage_type (ir_node *node, linkage_type *lt);
+
+inline ir_node *get_Call_mem (ir_node *node);
+inline void     set_Call_mem (ir_node *node, ir_node *mem);
+inline ir_node *get_Call_ptr (ir_node *node);
+inline void     set_Call_ptr (ir_node *node, ir_node *ptr);
+inline int      get_Call_arity (ir_node *node);
+/* inline void     set_Call_arity (ir_node *node, ir_node *arity); */
+inline ir_node *get_Call_param (ir_node *node, int pos);
+inline void     set_Call_param (ir_node *node, int pos, ir_node *param);
+inline type_method *get_Call_type (ir_node *node);
+inline void         set_Call_type (ir_node *node, type_method *type);
+
+/* For unary and binary arithmetic operations the access to the
+   operands can be factored out.  Left is the first, right the
+   second arithmetic value  as listed in tech report 1999-44.
+   unops are: Minus, Abs, Not, Conv
+   binops are: Add, Sub, Mul, Quot, DivMod, Div, Mod, And, Or, Eor, Shl,
+   Shr, Shrs, Rot, Cmp */
+inline int      is_unop (ir_node *node);
+inline ir_node *get_unop_op (ir_node *node);
+inline void     set_unop_op (ir_node *node, ir_node *op);
+inline int      is_binop (ir_node *node);
+inline ir_node *get_binop_left (ir_node *node);
+inline void     set_binop_left (ir_node *node, ir_node *left);
+inline ir_node *get_binop_right (ir_node *node);
+inline void     set_binop_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Add_left (ir_node *node);
+inline void     set_Add_left (ir_node *node, ir_node *left);
+inline ir_node *get_Add_right (ir_node *node);
+inline void     set_Add_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Sub_left (ir_node *node);
+inline void     set_Sub_left (ir_node *node, ir_node *left);
+inline ir_node *get_Sub_right (ir_node *node);
+inline void     set_Sub_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Minus_op (ir_node *node);
+inline void     set_Minus_op (ir_node *node, ir_node *op);
+
+inline ir_node *get_Mul_left (ir_node *node);
+inline void     set_Mul_left (ir_node *node, ir_node *left);
+inline ir_node *get_Mul_right (ir_node *node);
+inline void     set_Mul_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Quot_left (ir_node *node);
+inline void     set_Quot_left (ir_node *node, ir_node *left);
+inline ir_node *get_Quot_right (ir_node *node);
+inline void     set_Quot_right (ir_node *node, ir_node *right);
+inline ir_node *get_Quot_mem (ir_node *node);
+inline void     set_Quot_mem (ir_node *node, ir_node *mem);
+
+inline ir_node *get_DivMod_left (ir_node *node);
+inline void     set_DivMod_left (ir_node *node, ir_node *left);
+inline ir_node *get_DivMod_right (ir_node *node);
+inline void     set_DivMod_right (ir_node *node, ir_node *right);
+inline ir_node *get_DivMod_mem (ir_node *node);
+inline void     set_DivMod_mem (ir_node *node, ir_node *mem);
+
+inline ir_node *get_Div_left (ir_node *node);
+inline void     set_Div_left (ir_node *node, ir_node *left);
+inline ir_node *get_Div_right (ir_node *node);
+inline void     set_Div_right (ir_node *node, ir_node *right);
+inline ir_node *get_Div_mem (ir_node *node);
+inline void     set_Div_mem (ir_node *node, ir_node *mem);
+
+inline ir_node *get_Mod_left (ir_node *node);
+inline void     set_Mod_left (ir_node *node, ir_node *left);
+inline ir_node *get_Mod_right (ir_node *node);
+inline void     set_Mod_right (ir_node *node, ir_node *right);
+inline ir_node *get_Mod_mem (ir_node *node);
+inline void     set_Mod_mem (ir_node *node, ir_node *mem);
+
+inline ir_node *get_Abs_op (ir_node *node);
+inline void     set_Abs_op (ir_node *node, ir_node *op);
+
+inline ir_node *get_And_left (ir_node *node);
+inline void     set_And_left (ir_node *node, ir_node *left);
+inline ir_node *get_And_right (ir_node *node);
+inline void     set_And_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Or_left (ir_node *node);
+inline void     set_Or_left (ir_node *node, ir_node *left);
+inline ir_node *get_Or_right (ir_node *node);
+inline void     set_Or_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Eor_left (ir_node *node);
+inline void     set_Eor_left (ir_node *node, ir_node *left);
+inline ir_node *get_Eor_right (ir_node *node);
+inline void     set_Eor_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Not_op (ir_node *node);
+inline void     set_Not_op (ir_node *node, ir_node *op);
+
+inline ir_node *get_Cmp_left (ir_node *node);
+inline void     set_Cmp_left (ir_node *node, ir_node *left);
+inline ir_node *get_Cmp_right (ir_node *node);
+inline void     set_Cmp_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Shl_left (ir_node *node);
+inline void     set_Shl_left (ir_node *node, ir_node *left);
+inline ir_node *get_Shl_right (ir_node *node);
+inline void     set_Shl_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Shr_left (ir_node *node);
+inline void     set_Shr_left (ir_node *node, ir_node *left);
+inline ir_node *get_Shr_right (ir_node *node);
+inline void     set_Shr_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Shrs_left (ir_node *node);
+inline void     set_Shrs_left (ir_node *node, ir_node *left);
+inline ir_node *get_Shrs_right (ir_node *node);
+inline void     set_Shrs_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Rot_left (ir_node *node);
+inline void     set_Rot_left (ir_node *node, ir_node *left);
+inline ir_node *get_Rot_right (ir_node *node);
+inline void     set_Rot_right (ir_node *node, ir_node *right);
+
+inline ir_node *get_Conv_op (ir_node *node);
+inline void     set_Conv_op (ir_node *node, ir_node *op);
+
+inline int      get_Phi_n_preds (ir_node *node);
+/* inline void     set_Phi_n_preds (ir_node *node, int n_preds); */
+inline ir_node *get_Phi_pred (ir_node *node, int pos);
+inline void     set_Phi_pred (ir_node *node, int pos, ir_node *pred);
+
+inline ir_node *get_Load_mem (ir_node *node);
+inline void     set_Load_mem (ir_node *node, ir_node *mem);
+inline ir_node *get_Load_ptr (ir_node *node);
+inline void     set_Load_ptr (ir_node *node, ir_node *ptr);
+
+inline ir_node *get_Store_mem (ir_node *node);
+inline void     set_Store_mem (ir_node *node, ir_node *mem);
+inline ir_node *get_Store_ptr (ir_node *node);
+inline void     set_Store_ptr (ir_node *node, ir_node *ptr);
+inline ir_node *get_Store_value (ir_node *node);
+inline void     set_Store_value (ir_node *node, ir_node *value);
+
+inline ir_node *get_Alloc_mem (ir_node *node);
+inline void     set_Alloc_mem (ir_node *node, ir_node *mem);
+inline ir_node *get_Alloc_size (ir_node *node);
+inline void     set_Alloc_size (ir_node *node, ir_node *size);
+inline type    *get_Alloc_type (ir_node *node);
+inline void     set_Alloc_type (ir_node *node, type *type);
+inline where_alloc  get_Alloc_where (ir_node *node);
+inline void         set_Alloc_where (ir_node *node, where_alloc where);
+
+inline ir_node *get_Free_mem (ir_node *node);
+inline void     set_Free_mem (ir_node *node, ir_node *mem);
+inline ir_node *get_Free_ptr (ir_node *node);
+inline void     set_Free_ptr (ir_node *node, ir_node *ptr);
+inline ir_node *get_Free_size (ir_node *node);
+inline void     set_Alloc_size (ir_node *node, ir_node *size);
+inline type    *get_Free_type (ir_node *node);
+inline void     set_Free_type (ir_node *node, type *type);
+
+inline int      get_Sync_n_preds (ir_node *node);
+/* inline void     set_Sync_n_preds (ir_node *node, int n_preds); */
+inline ir_node *get_Sync_pred (ir_node *node, int pos);
+inline void     set_Sync_pred (ir_node *node, int pos, ir_node *pred);
+
+inline ir_node *get_Proj_pred (ir_node *node);
+inline void     set_Proj_pred (ir_node *node, ir_node *pred);
+inline long     get_Proj_proj (ir_node *node);
+inline void     set_Proj_proj (ir_node *node, long proj);
+
+inline int      get_Tuple_n_preds (ir_node *node);
+/* inline void     set_Tuple_n_preds (ir_node *node, int n_preds); */
+inline ir_node *get_Tuple_pred (ir_node *node, int pos);
+inline void     set_Tuple_pred (ir_node *node, int pos, ir_node *pred);
+
+inline ir_node *get_Id_pred (ir_node *node);
+inline void     set_Id_pred (ir_node *node, ir_node *pred);
+
+
+
+/******************************************************************/
+/*  Auxiliary routines                                            */
+/******************************************************************/
+
+/* returns operand of node if node is a Proj. */
+inline ir_node *skip_Proj (ir_node *node);
+/* returns operand of node if node is a Id */
+inline ir_node *skip_nop  (ir_node *node);
+/* returns true if node is a Bad node. */
+inline int      is_Bad    (ir_node *node);
+/* returns true if the node is not a Block */
+inline int      is_no_Block (ir_node *node);
+/* Returns true if the operation manipulates control flow:
+   Start, End, Jmp, Cond, Return, Raise */
+int is_cfop(ir_node *node);
+/* Returns true if the operation can change the control flow because
+   of a exception. */
+int is_fragile_op(ir_node *node);
+
+# endif /* _IRNODE_H_ */
diff --git a/ir/ir/irop.c b/ir/ir/irop.c
new file mode 100644 (file)
index 0000000..b4affde
--- /dev/null
@@ -0,0 +1,127 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer
+**
+*/
+
+# include "irop.h"
+# include "irnode.h"
+
+ir_op *op_Block;
+
+ir_op *op_Start;
+ir_op *op_End;
+ir_op *op_Jmp;
+ir_op *op_Cond;
+ir_op *op_Return;
+ir_op *op_Raise;
+
+ir_op *op_Sel;
+
+ir_op *op_Const;
+ir_op *op_SymConst;
+
+ir_op *op_Call;
+ir_op *op_Add;
+ir_op *op_Sub;
+ir_op *op_Minus;
+ir_op *op_Mul;
+ir_op *op_Quot;
+ir_op *op_DivMod;
+ir_op *op_Div;
+ir_op *op_Mod;
+ir_op *op_Abs;
+ir_op *op_And;
+ir_op *op_Or;
+ir_op *op_Eor;
+ir_op *op_Not;
+ir_op *op_Cmp;
+ir_op *op_Shl;
+ir_op *op_Shr;
+ir_op *op_Shrs;
+ir_op *op_Rot;
+ir_op *op_Conv;
+
+ir_op *op_Phi;
+
+ir_op *op_Load;
+ir_op *op_Store;
+ir_op *op_Alloc;
+ir_op *op_Free;
+ir_op *op_Sync;
+
+ir_op *op_Tuple;
+ir_op *op_Proj;
+ir_op *op_Id;
+ir_op *op_Bad;
+
+
+ir_op *
+new_ir_op (opcode code, ident *name, size_t attr_size, int labeled)
+{
+  ir_op *res;
+
+  res = (ir_op *) xmalloc (sizeof (ir_op));
+  res->code = code;
+  res->name = name;
+  res->attr_size = attr_size;
+  res->labeled = labeled;   /* For vcg dumping.
+                               Set labeled = 1 if the edges shuld be
+                              enumarated, otherwise set labeled = 0. */
+  return res;
+}
+
+
+void
+init_op(void)
+{
+  op_Block = new_ir_op (iro_Block, id_from_str ("Block", 5), sizeof (block_attr), 1);
+
+  op_Start = new_ir_op (iro_Start, id_from_str ("Start", 5), sizeof (block_attr), 1);
+  op_End = new_ir_op (iro_End, id_from_str ("End", 3), sizeof (block_attr), 1);
+  op_Jmp = new_ir_op (iro_Jmp, id_from_str ("Jmp", 3), 0, 0);
+  op_Cond = new_ir_op (iro_Cond, id_from_str ("Cond", 4), 0, 1);
+  op_Return = new_ir_op (iro_Return, id_from_str ("Return", 6), 0, 1);
+  op_Raise = new_ir_op (iro_Raise, id_from_str ("Raise", 5), 0, 1);
+
+  op_Const = new_ir_op (iro_Const, id_from_str ("Const", 5), sizeof (struct tarval *), 0);
+  op_SymConst = new_ir_op (iro_SymConst, id_from_str ("SymConst", 8),
+                          sizeof (symconst_attr), 0);
+
+  op_Sel = new_ir_op (iro_Sel, id_from_str ("Sel", 3), sizeof (entity *), 1);
+
+  op_Call = new_ir_op (iro_Call, id_from_str ("Call", 4), sizeof (type_method *), 1);
+  op_Add = new_ir_op (iro_Add, id_from_str ("Add", 3), 0, 0);
+  op_Minus = new_ir_op (iro_Minus, id_from_str ("Minus", 3), 0, 0);
+  op_Sub = new_ir_op (iro_Sub, id_from_str ("Sub", 3), 0, 1);
+  op_Mul = new_ir_op (iro_Mul, id_from_str ("Mul", 3), 0, 0);
+  op_Quot = new_ir_op (iro_Quot, id_from_str ("Quot", 4), 0, 1);
+  op_DivMod = new_ir_op (iro_DivMod, id_from_str ("DivMod", 6), 0, 1);
+  op_Div = new_ir_op (iro_Div, id_from_str ("Div", 3), 0, 1);
+  op_Mod = new_ir_op (iro_Mod, id_from_str ("Mod", 3), 0, 1);
+  op_Abs = new_ir_op (iro_Abs, id_from_str ("Abs", 3), 0, 0);
+  op_And = new_ir_op (iro_And, id_from_str ("And", 3), 0, 0);
+  op_Or = new_ir_op (iro_Or, id_from_str ("Or", 2), 0, 0);
+  op_Eor = new_ir_op (iro_Eor, id_from_str ("Eor", 3), 0, 0);
+  op_Not = new_ir_op (iro_Not, id_from_str ("Not", 3), 0, 0);
+  op_Cmp = new_ir_op (iro_Cmp, id_from_str ("Cmp", 3), 0, 1);
+  op_Shl = new_ir_op (iro_Shl, id_from_str ("Shl", 3), 0, 1);
+  op_Shr = new_ir_op (iro_Shr, id_from_str ("Shr", 3), 0, 1);
+  op_Shrs = new_ir_op (iro_Shrs, id_from_str ("Shrs", 3), 0, 0);
+  op_Rot = new_ir_op (iro_Rot, id_from_str ("Rot", 3), 0, 0);
+  op_Conv = new_ir_op (iro_Conv, id_from_str ("Conv", 4), 0, 1);
+
+  op_Phi = new_ir_op (iro_Phi, id_from_str ("Phi", 3), sizeof (int), 1);
+
+  op_Load = new_ir_op (iro_Load, id_from_str ("Load", 4), 0, 1);
+  op_Store = new_ir_op (iro_Store, id_from_str ("Store", 5), 0, 1);
+  op_Alloc = new_ir_op (iro_Alloc, id_from_str ("Alloc", 5), sizeof (alloc_attr), 1);
+  op_Free = new_ir_op (iro_Free, id_from_str ("Free", 5), sizeof (type *), 1);
+  op_Sync = new_ir_op (iro_Sync, id_from_str ("Sync", 4), 0, 0);
+
+  op_Proj = new_ir_op (iro_Proj, id_from_str ("Proj", 4), sizeof (long), 1);
+  op_Tuple = new_ir_op (iro_Tuple, id_from_str ("Tuple", 5), 0, 1);
+  op_Id = new_ir_op (iro_Id, id_from_str ("Id", 2), 0, 0);
+  op_Bad = new_ir_op (iro_Bad, id_from_str ("Bad", 3), 0, 0);
+}
diff --git a/ir/ir/irop.h b/ir/ir/irop.h
new file mode 100644 (file)
index 0000000..b4eae58
--- /dev/null
@@ -0,0 +1,87 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer
+**
+*/
+
+# ifndef _IROP_H_
+# define _IROP_H_
+
+# include "ident.h"
+# include "type.h"
+
+typedef enum {
+  iro_Block,
+  iro_Start, iro_End, iro_Jmp, iro_Cond, iro_Return, iro_Raise,
+  iro_Const, iro_SymConst,
+  iro_Sel,
+  iro_Call, iro_Add, iro_Sub, iro_Minus, iro_Mul, iro_Quot, iro_DivMod,
+  iro_Div, iro_Mod, iro_Abs, iro_And, iro_Or, iro_Eor, iro_Not,
+  iro_Cmp, iro_Shl, iro_Shr, iro_Shrs, iro_Rot, iro_Conv,
+  iro_Phi,
+  iro_Load, iro_Store, iro_Alloc, iro_Free, iro_Sync,
+  iro_Proj, iro_Tuple, iro_Id, iro_Bad
+} opcode;
+
+typedef struct {
+  opcode code;
+  ident *name;
+  size_t attr_size;
+  int labeled;
+} ir_op;
+
+extern ir_op *op_Block;
+
+extern ir_op *op_Start;
+extern ir_op *op_End;
+extern ir_op *op_Jmp;
+extern ir_op *op_Cond;
+extern ir_op *op_Return;
+extern ir_op *op_Raise;
+
+extern ir_op *op_Sel;
+
+extern ir_op *op_Const;
+extern ir_op *op_SymConst;
+
+extern ir_op *op_Call;
+extern ir_op *op_Add;
+extern ir_op *op_Sub;
+extern ir_op *op_Minus;
+extern ir_op *op_Mul;
+extern ir_op *op_Quot;
+extern ir_op *op_DivMod;
+extern ir_op *op_Div;
+extern ir_op *op_Mod;
+extern ir_op *op_Abs;
+extern ir_op *op_And;
+extern ir_op *op_Or;
+extern ir_op *op_Eor;
+extern ir_op *op_Not;
+extern ir_op *op_Cmp;
+extern ir_op *op_Shl;
+extern ir_op *op_Shr;
+extern ir_op *op_Shrs;
+extern ir_op *op_Rot;
+extern ir_op *op_Conv;
+
+extern ir_op *op_Phi;
+
+extern ir_op *op_Load;
+extern ir_op *op_Store;
+extern ir_op *op_Alloc;
+extern ir_op *op_Free;
+
+extern ir_op *op_Sync;
+
+extern ir_op *op_Tuple;
+extern ir_op *op_Proj;
+extern ir_op *op_Id;
+extern ir_op *op_Bad;
+
+/* create a new ir operation */
+ir_op * new_ir_op (opcode code, ident *name, size_t attr_size, int labeled);
+void init_op (void);
+
+# endif /* _IROP_H_ */
diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c
new file mode 100644 (file)
index 0000000..99e8322
--- /dev/null
@@ -0,0 +1,1049 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** iropt --- optimizations intertwined with IR construction.
+*/
+
+# include "iropt.h"
+# include "ircons.h"
+# include "irgwalk.h"
+# include "tv.h"
+
+/* Trivial inlineable routine for copy propagation.
+   Does follow Ids, needed to optimize inlined code. */
+static inline ir_node *
+follow_Id (ir_node *n)
+{
+  while (get_irn_op (n) == op_Id) n = get_Id_pred (n);
+  return n;
+}
+
+
+static inline tarval *
+value_of (ir_node *n)
+{
+  if ((n != NULL) && (get_irn_op(n) == op_Const))
+    return get_Const_tarval(n);
+  else
+    return NULL;
+}
+
+
+/* if n can be computed, return the value, else NULL. Performs
+   constant Folding. GL: Only if n is arithmetic operator? */
+tarval *
+computed_value (ir_node *n)
+{
+  tarval *res;
+
+  ir_node *a = NULL, *b = NULL;         /* initialized to shut up gcc */
+  tarval *ta = NULL, *tb = NULL; /* initialized to shut up gcc */
+
+  res = NULL;
+
+  /* get the operands we will work on for simple cases. */
+  if (is_binop(n)) {
+    a = get_binop_left(n);
+    b = get_binop_right(n);
+  } else if (is_unop(n)) {
+    a = get_unop_op(n);
+  }
+
+  /* if the operands are constants, get the target value, else set it NULL.
+     (a and b may be NULL if we treat a node that is no computation.) */
+  ta = value_of (a);
+  tb = value_of (b);
+
+  /* Perform the constant evaluation / computation. */
+  switch (get_irn_opcode(n)) {
+  case iro_Const:
+    res = get_Const_tarval(n);
+  case iro_Add:
+    if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))
+       && (get_irn_mode(a) != mode_p)) {
+      res = tarval_add (ta, tb);
+    }
+    break;
+  case iro_Sub:
+    if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))
+       && (get_irn_mode(a) != mode_p)) {
+      res = tarval_sub (ta, tb);
+    } else if (a == b) {
+      res = tarval_mode_null [get_irn_modecode (n)];
+    }
+    break;
+  case iro_Minus:
+      if (ta && mode_is_float(get_irn_mode(a)))
+        res = /*tarval_minus (ta);*/ res;
+    break;
+  case iro_Mul:
+    if (ta && tb) /* tarval_mul tests for equivalent modes itself */ {
+      res = tarval_mul (ta, tb);
+    } else {
+      /* calls computed_value recursive and returns the 0 with proper
+         mode.  Why is this an extra case? */
+      tarval *v;
+      if (   (tarval_classify ((v = computed_value (a))) == 0)
+         || (tarval_classify ((v = computed_value (b))) == 0)) {
+       res = v;
+      }
+    }
+    break;
+  case iro_Abs:
+    if (ta)
+      res = /*tarval_abs (ta);*/ res;
+    /* allowded or problems with max/min ?? */
+    break;
+  case iro_And:
+    if (ta && tb) {
+      res = tarval_and (ta, tb);
+    } else {
+      tarval *v;
+      if (   (tarval_classify ((v = computed_value (a))) == 0)
+         || (tarval_classify ((v = computed_value (b))) == 0)) {
+       res = v;
+      }
+    }
+    break;
+  case iro_Or:
+    if (ta && tb) {
+      res = tarval_or (ta, tb);
+    } else {
+      tarval *v;
+      if (   (tarval_classify ((v = computed_value (a))) == -1)
+         || (tarval_classify ((v = computed_value (b))) == -1)) {
+       res = v;
+      }
+    }
+    break;
+  case iro_Eor: if (ta && tb) { res = tarval_eor (ta, tb); } break;
+  case iro_Not: if(ta) { /*res = tarval_not (ta)*/; } break;
+  case iro_Shl: if (ta && tb) { res = tarval_shl (ta, tb); } break;
+  case iro_Shr: if (ta && tb) { res = tarval_shr (ta, tb); } break;
+  case iro_Shrs: if(ta && tb) { /*res = tarval_shrs (ta, tb)*/; } break;
+  case iro_Rot: if(ta && tb) { /*res = tarval_rot (ta, tb)*/; } break;
+  case iro_Conv: if (ta) { res = tarval_convert_to (ta, get_irn_mode (n)); }
+    break;
+  case iro_Proj:
+    {
+      ir_node *aa, *ab;
+
+      a = get_Proj_pred(n);
+      /* Optimize Cmp nodes.
+        This performs a first step of unreachable code elimination.
+        Proj can not be computed, but folding a Cmp above the Proj here is
+        not as wasteful as folding a Cmp into a Tuple of 16 Consts of which
+        only 1 is used.
+         There are several case where we can evaluate a Cmp node:
+         1. The nodes compared are both the same.  If we compare for
+            equal, this will return true, else it will return false.
+            This step relies on cse.
+         2. The predecessors of Cmp are target values.  We can evaluate
+            the Cmp.
+         3. The predecessors are Allocs or void* constants.  Allocs never
+            return NULL, they raise an exception.   Therefore we can predict
+            the Cmp result. */
+      if (get_irn_op(a) == op_Cmp) {
+        aa = get_Cmp_left(a);
+        ab = get_Cmp_right(a);
+       if (aa == ab) { /* 1.: */
+          /* This is a tric with the bits used for encoding the Cmp
+             Proj numbers, the following statement is not the same:
+          res = tarval_from_long (mode_b, (get_Proj_proj(n) == Eq)):    */
+         res = tarval_from_long (mode_b, (get_Proj_proj(n) & irpn_Eq));
+       } else {
+         tarval *taa = computed_value (aa);
+         tarval *tab = computed_value (ab);
+         if (taa && tab) { /* 2.: */
+            /* strange checks... */
+           ir_pncmp flags = tarval_comp (taa, tab);
+           if (flags != irpn_False) {
+              res = tarval_from_long (mode_b, get_Proj_proj(n) & flags);
+           }
+         } else {  /* check for 3.: */
+            ir_node *aaa = skip_nop(skip_Proj(aa));
+            ir_node *aba = skip_nop(skip_Proj(ab));
+           if (   (   (/* aa is ProjP and aaa is Alloc */
+                           (get_irn_op(aa) == op_Proj)
+                       && (get_irn_mode(aa) == mode_p)
+                        && (get_irn_op(aaa) == op_Alloc))
+                    && (   (/* ab is constant void */
+                               (get_irn_op(ab) == op_Const)
+                            && (get_irn_mode(ab) == mode_p)
+                            && (get_Const_tarval(ab) == tarval_p_void))
+                       || (/* ab is other Alloc */
+                               (get_irn_op(ab) == op_Proj)
+                           && (get_irn_mode(ab) == mode_p)
+                            && (get_irn_op(aba) == op_Alloc)
+                           && (aaa != aba))))
+               || (/* aa is void and aba is Alloc */
+                       (get_irn_op(aa) == op_Const)
+                    && (get_irn_mode(aa) == mode_p)
+                    && (get_Const_tarval(aa) == tarval_p_void)
+                    && (get_irn_op(ab) == op_Proj)
+                   && (get_irn_mode(ab) == mode_p)
+                    && (get_irn_op(aba) == op_Alloc)))
+             /* 3.: */
+             res = tarval_from_long (mode_b, get_Proj_proj(n) & irpn_Ne);
+         }
+       }
+      } else {
+        // printf(" # comp_val: Proj node, not optimized\n");
+      }
+    }
+    break;
+  default:  ;
+  }
+
+  return res;
+}  /* compute node */
+
+
+
+/* returns 1 if the a and b are pointers to different locations. */
+bool
+different_identity (ir_node *a, ir_node *b)
+{
+  assert (get_irn_mode (a) == mode_p
+          && get_irn_mode (b) == mode_p);
+
+  if (get_irn_op (a) == op_Proj && get_irn_op(b) == op_Proj) {
+    ir_node *a1 = get_Proj_pred (a);
+    ir_node *b1 = get_Proj_pred (b);
+    if (a1 != b1 && get_irn_op (a1) == op_Alloc
+                 && get_irn_op (b1) == op_Alloc)
+      return 1;
+  }
+  return 0;
+}
+
+
+/* equivalent_node returns a node equivalent to N.  It skips all nodes that
+   perform no actual computation, as, e.g., the Id nodes.  It does not create
+   new nodes.  It is therefore safe to free N if the node returned is not N.
+   If a node returns a Tuple we can not just skip it.  If the size of the
+   in array fits, we transform n into a tuple (e.g., Div). */
+static ir_node *
+equivalent_node (ir_node *n)
+{
+  int ins;
+  ir_node *a = NULL; /* to shutup gcc */
+  ir_node *b = NULL; /* to shutup gcc */
+  ir_node *c = NULL; /* to shutup gcc */
+
+  ins = get_irn_arity (n);
+
+  /* get the operands we will work on */
+  if (is_binop(n)) {
+    a = get_binop_left(n);
+    b = get_binop_right(n);
+  } else if (is_unop(n)) {
+    a = get_unop_op(n);
+  }
+
+
+  /* skip unnecessary nodes. */
+  switch (get_irn_opcode (n)) {
+  case iro_Block:
+    {
+      /* The Block constructor does not call optimize, therefore
+         dead blocks are not removed without an extra optimizing
+         pass through the graph. */
+      assert(get_Block_matured(n));
+
+      /* a single entry Region following a single exit Region can be merged */
+      /* !!! Beware, all Phi-nodes of n must have been optimized away.
+        This is true, as the block is matured before optimize is called.   */
+      if (get_Block_n_cfgpreds(n) == 1
+         && get_irn_op(get_Block_cfgpred(n, 0)) == op_Jmp) {
+       n = get_nodes_Block(get_Block_cfgpred(n, 0));
+      } else if (n != current_ir_graph->start_block) {
+       int i;
+
+       /* If all inputs are dead, this block is dead too, except if it is
+           the start block.  This is a step of unreachable code elimination */
+
+       for (i = 0; i < get_Block_n_cfgpreds(n); i++) {
+         if (!is_Bad(get_Block_cfgpred(n, i))) break;
+       }
+       if (i == get_Block_n_cfgpreds(n))
+         n = new_Bad();
+      }
+    }
+    break;
+
+  case iro_Jmp:  /* GL: ??? Why not same for op_Raise?? */
+    /* unreachable code elimination */
+    if (is_Bad(get_nodes_Block(n)))  n = new_Bad();
+    break;
+  /* GL: Why isn't there a case that checks whether input ot Cond is
+     constant true or false?  For unreachable code elimination
+     is this done in Proj? It's not here as it generates a new node,
+     a Jmp. It is in transform_node. *
+  case iro_Cond:
+    break;
+  */
+    /* remove stuff as x+0, x*1 x&true ... constant expression evaluation */
+  case iro_Or:  if (a == b) {n = a; break;}
+  case iro_Add:
+  case iro_Eor:
+    { tarval *tv;
+      ir_node *on;
+      /* After running compute_node there is only one constant predecessor.
+         Find this predecessors value and remember the other node: */
+      if ((tv = computed_value (a))) {
+       on = b;
+      } else if ((tv = computed_value (b))) {
+       on = a;
+      } else break;
+
+      /* If this predecessors constant value is zero, the operation is
+         unnecessary. Remove it: */
+      if (tarval_classify (tv) == 0) {
+       n = on;
+      }
+    }
+    break;
+  case iro_Sub:
+  case iro_Shl:
+  case iro_Shr:
+  case iro_Shrs:
+  case iro_Rot:
+    /* these operations are not commutative.  Test only one predecessor. */
+    if (tarval_classify (computed_value (b)) == 0) {
+      n = a;
+      /* Test if b > #bits of a ==> return 0 / divide b by #bits
+         --> transform node? */
+    }
+    break;
+  case iro_Not:   /* NotNot x == x */
+  case iro_Minus: /* --x == x */  /* ??? Is this possible or can --x raise an
+                                    out of bounds exception if min =! max? */
+    if (get_irn_op(get_unop_op(n)) == get_irn_op(n))
+      n = get_unop_op(get_unop_op(n));
+    break;
+  case iro_Mul:
+    /* Mul is commutative and has again an other neutral element. */
+    if (tarval_classify (computed_value (a)) == 1) {
+      n = b;
+    } else if (tarval_classify (computed_value (b)) == 1) {
+      n = a;
+    }
+    break;
+  case iro_Div:
+    /* Div is not commutative. */
+    if (tarval_classify (computed_value (b)) == 1) { /* div(x, 1) == x */
+      /* Turn Div into a tuple (mem, bad, a) */
+      ir_node *mem = get_Div_mem(n);
+      turn_into_tuple(n, 3);
+      set_Tuple_pred(n, 0, mem);
+      set_Tuple_pred(n, 1, new_Bad());
+      set_Tuple_pred(n, 2, a);
+    }
+    break;
+    /* GL: Why are they skipped?  DivMod allocates new nodes --> it's
+       teated in transform node.
+  case iro_Mod, Quot, DivMod
+    */
+  case iro_And:
+    if (a == b) n = a;
+    /* And has it's own neutral element */
+    else if (tarval_classify (computed_value (a)) == -1) {
+      n = b;
+    } else if (tarval_classify (computed_value (b)) == -1) {
+      n = a;
+    }
+    break;
+  case iro_Conv:
+    if (get_irn_mode(n) == get_irn_mode(a)) { /* No Conv necessary */
+      n = a;
+    } else if (get_irn_mode(n) == mode_b) {
+      if (get_irn_op(a) == op_Conv &&
+         get_irn_mode (get_Conv_op(a)) == mode_b) {
+       n = get_Conv_op(a);     /* Convb(Conv*(xxxb(...))) == xxxb(...) */
+      }
+    }
+    break;
+
+  case iro_Phi:
+    {
+      /* Several optimizations:
+         - no Phi in start block.
+         - remove Id operators that are inputs to Phi
+         - fold Phi-nodes, iff they have only one predecessor except
+           themselves.
+      */
+      int i, n_preds;
+      ir_node *block = NULL;     /* to shutup gcc */
+      ir_node *first_val = NULL; /* to shutup gcc */
+      ir_node *scnd_val = NULL;  /* to shutup gcc */
+
+      n_preds = get_Phi_n_preds(n);
+
+      block = get_nodes_Block(n);
+      assert(get_irn_op (block) == op_Block);
+
+      /* there should be no Phi nodes in the Start region. */
+      if (block == current_ir_graph->start_block) {
+       n = new_Bad();
+       break;
+      }
+
+      if (n_preds == 0) {      /* Phi of dead Region without predecessors. */
+        // GL: why not return new_Bad?
+       break;
+      }
+
+#if 0
+      /* first we test for a special case: */
+      /* Confirm is a special node fixing additional information for a
+         value that is known at a certain point.  This is useful for
+         dataflow analysis. */
+      if (n_preds == 2) {
+       ir_node *a = follow_Id (get_Phi_pred(n, 0));
+       ir_node *b = follow_Id (get_Phi_pred(n, 1));
+       if (   (get_irn_op(a) == op_Confirm)
+            && (get_irn_op(b) == op_Confirm)
+            && (follow_Id (get_irn_n(a, 0)) == follow_Id(get_irn_n(b, 0)))
+            && (get_irn_n(a, 1) == get_irn_n (b, 1))
+           && (a->data.num == (~b->data.num & irpn_True) )) {
+         n = follow_Id (get_irn_n(a, 0));
+         break;
+       }
+      }
+#endif
+
+      /* Find first non-self-referencing input */
+      for (i = 0;  i < n_preds;  ++i) {
+        first_val = follow_Id(get_Phi_pred(n, i));
+        /* skip Id's */
+        set_Phi_pred(n, i, first_val);
+       if (   (first_val != n)                            /* not self pointer */
+            && (get_irn_op(first_val) != op_Bad)      /* value not dead */
+            && !(is_Bad (get_Block_cfgpred(block, i))) ) { /* not dead control flow */
+         break;                         /* then found first value. */
+       }
+      }
+
+      /* A totally Bad or self-referencing Phi */
+      if (i > n_preds) { n = new_Bad();  break; }
+
+      scnd_val = NULL;
+
+      /* follow_Id () for rest of inputs, determine if any of these
+        are non-self-referencing */
+      while (++i < n_preds) {
+        scnd_val = follow_Id(get_Phi_pred(n, i));
+        /* skip Id's */
+        set_Phi_pred(n, i, scnd_val);
+        if (   (scnd_val != n)
+           && (scnd_val != first_val)
+            && (get_irn_op(scnd_val) != op_Bad)
+            && !(is_Bad (get_Block_cfgpred(block, i))) ) {
+          break;
+       }
+      }
+
+      /* Fold, if no multiple distinct non-self-referencing inputs */
+      if (i > n_preds) {
+       n = a;
+      } else {
+      /* skip the remaining Ids. */
+       while (++i < n_preds)
+         set_Phi_pred(n, i, follow_Id(get_Phi_pred(n, i)));
+      }
+    }
+    break;
+
+  case iro_Load:
+    {
+      a = skip_Proj(get_Load_mem(n));
+      b = skip_Proj(get_Load_ptr(n));
+
+      if (get_irn_op(a) == op_Store) {
+        if ( different_identity (b, get_Store_ptr(a))) {
+          /* load and store use different pointers, therefore load
+             needs not take store's memory but the state before. */
+          set_Load_mem (n, get_Store_mem(a));
+       } else if (( 0 /* ???didn't get cryptic test that returns 0 */ )) {
+        }
+      }
+    }
+      break;
+  case iro_Store:
+    /* remove unnecessary store. */
+    {
+      a = skip_Proj(get_Store_mem(n));
+      b = get_Store_ptr(n);
+      c = skip_Proj(get_Store_value(n));
+
+      if (get_irn_op(a) == op_Store
+          && get_Store_ptr(a) == b
+          && skip_Proj(get_Store_value(a)) == c) {
+        /* We have twice exactly the same store -- a write after write. */
+       n = a;
+      } else if (get_irn_op(c) == op_Load
+                && (a == c || skip_Proj(get_Load_mem(c)) == a)
+                 && get_Load_ptr(c) == b )
+                /* !!!??? and a cryptic test */ {
+        /* We just loaded the value from the same memory, i.e., the store
+           doesn't change the memory -- a write after read. */
+        turn_into_tuple(n, 2);
+        set_Tuple_pred(n, 0, a);
+        set_Tuple_pred(n, 1, new_Bad());
+      }
+    }
+    break;
+
+  case iro_Proj:
+    {
+      a = get_Proj_pred(n);
+
+      if ( get_irn_op(a) == op_Tuple) {
+        /* Remove the Tuple/Proj combination. */
+       if ( get_Proj_proj(n) <= get_Tuple_n_preds(a) ) {
+         n = get_Tuple_pred(a, get_Proj_proj(n));
+       } else {
+          assert(0); /* This should not happen?! (GL added this assert) */
+         n = new_Bad();
+       }
+      } else if (get_irn_mode(n) == mode_X &&
+                is_Bad(get_nodes_Block(n))) {
+        /* Remove dead control flow. */
+       n = new_Bad();
+      }
+    }
+    break;
+
+  case iro_Id:
+    n = follow_Id (n);
+    break;
+
+  default: break;
+  }
+
+  return n;
+} /* end equivalent_node() */
+
+
+#if 0
+/* tries several [inplace] [optimizing] transformations and returns a
+   equivalent node.  The difference to equivalent_node is that these
+   transformations _do_ generate new nodes, and thus the old node must
+   not be freed even if the equivalent node isn't the old one. */
+static ir_node *
+transform_node (ir_node *n)
+{
+
+  ir_node *a, *b;
+  tarval *ta, *tb;
+
+  switch (get_irn_opcode(n)) {
+  case iro_DivMod: {
+    int evaluated = 0;
+    ir_mode *mode = get_irn_mode(a);
+
+    a = get_DivMod_left(n);
+    b = get_DivMod_right(n);
+
+    if (!(   mode_is_int(get_irn_mode(a))
+         && mode_is_int(get_irn_mode(b))))
+      break;
+
+    if (a == b) {
+      a = new_Const (mode, tarval_from_long (mode, 1));
+      b = new_Const (mode, tarval_from_long (mode, 0));
+      evaluated = 1;
+    } else {
+      ta = value_of(a);
+      tb = value_of(b);
+
+      if (tb) {
+       if (tarval_classify(tb) == 1) {
+         b = new_Const (mode, tarval_from_long (mode, 0));
+         evaluated = 1;
+       } else if (ta) {
+         tarval *resa, *resb;
+          resa = tarval_div (ta, tb);
+          if (!resa) break; /* Causes exception!!! Model by replacing through
+                              Jmp for X result!? */
+          resb = tarval_mod (ta, tb);
+          if (!resb) break; /* Causes exception! */
+         a = new_Const (mode, resa);
+         b = new_Const (mode, resb);
+         evaluated = 1;
+       }
+      } else if (tarval_classify (ta) == 0) {
+        b = a;
+       evaluated = 1;
+      }
+    }
+    if (evaluated) { /* replace by tuple */
+      ir_node *mem = get_DivMod_mem(n);
+      turn_into_tuple(n, 4);
+      set_Tuple_pred(n, 0, mem);
+      set_Tuple_pred(n, 1, new_Bad());
+      set_Tuple_pred(n, 2, a);
+      set_Tuple_pred(n, 3, b);
+    }
+  }
+  break;
+
+  case iro_Cond: {
+    /* Replace the Cond by a Jmp if it branches on a constant
+       condition. */
+    ir_node *jmp;
+
+    a = get_Cond_selector(n);
+    ta = value_of(a);
+
+    if (ta && (get_irn_mode(a) == mode_b)) {
+      /* It's a boolean Cond, branching on a boolean constant.
+         Replace it by a tuple (Bad, Jmp) or (Jmp, Bad) */
+      jmp = new_r_Jmp(current_ir_graph, get_nodes_Block(n));
+      turn_into_tuple(n, 2);
+      if (tv_val_b(ta) == 1)  /* GL: I hope this returns 1 if true */ {
+       set_Tuple_pred(n, 0, new_Bad());
+       set_Tuple_pred(n, 1, jmp);
+      } else {
+       set_Tuple_pred(n, 0, jmp);
+       set_Tuple_pred(n, 1, new_Bad());
+      }
+    } else if (ta && (get_irn_mode(a) == mode_I)) {
+      /* I don't want to allow Tuples smaller than the biggest Proj.
+         Also this tuple might get really big...
+         I generate the Jmp here, and remember it in link.  Link is used
+         when optimizing Proj. */
+      set_irn_link(n, new_r_Jmp(current_ir_graph, get_nodes_Block(n)));
+    } else if (   ((get_irn_op(get_Cond_selector(n)) == op_Eor)
+                   /* || (get_irn_op(get_Cond_selector(a)) == op_Not)*/)
+               && (get_irn_mode(get_Cond_selector(n)) == mode_b)
+               && (tarval_classify(computed_value(get_Eor_right(a))) == 1)) {
+      /* The Eor is a negate.  Generate a new Cond without the negate,
+         simulate the negate by exchanging the results. */
+      set_irn_link(n, new_r_Cond(current_ir_graph, get_nodes_Block(n),
+                                get_Eor_left(a)));
+    }
+  }
+  break;
+
+  case iro_Proj: {
+    a = get_Proj_pred(n);
+
+    if (  (get_irn_op(a) == op_Cond)
+        && get_irn_link(a)
+        && get_irn_op(get_irn_link(a)) == op_Cond) {
+    /* Use the better Cond if the Proj projs from a Cond which get's
+       its result from an Eor/Not. */
+      assert (   ((get_irn_op(get_Cond_selector(a)) == op_Eor)
+                  /* || (get_irn_op(get_Cond_selector(a)) == op_Not)*/)
+              && (get_irn_mode(get_Cond_selector(a)) == mode_b)
+             && (get_irn_op(get_irn_link(a)) == op_Cond)
+              && (get_Cond_selector(get_irn_link(a)) ==
+                  get_Eor_left(get_Cond_selector(a))));
+      set_Proj_pred(n, get_irn_link(a));
+      if (get_Proj_proj(n) == 0)
+        set_Proj_proj(n, 1);
+      else
+        set_Proj_proj(n, 0);
+    } else if (   (get_irn_op(a) == op_Cond)
+               && (get_irn_mode(get_Cond_selector(a)) == mode_I)
+               && value_of(a)) {
+      /* The Cond is a Switch on a Constant */
+      if (get_Proj_proj(n) == tv_val_CHIL(value_of(a))) {
+        /* The always taken branch, reuse the existing Jmp. */
+        if (!get_irn_link(a)) /* well, if it exists ;-> */
+          set_irn_link(a, new_r_Jmp(current_ir_graph, get_nodes_Block(n)));
+        assert(get_irn_op(get_irn_link(a)) == op_Jmp);
+        n = get_irn_link(a);
+      } else {
+        /* a never taken branch */
+        n = new_Bad();
+      }
+    }
+  }
+  break;
+  case iro_Eor: {
+    a = get_Eor_left(n);
+    b = get_Eor_right(n);
+
+    if (   (get_irn_mode(n) == mode_b)
+       && (get_irn_op(a) == op_Proj)
+        && (get_irn_mode(a) == mode_b)
+       && (tarval_classify (computed_value (b)) == 1)
+       && (get_irn_op(get_Proj_pred(a)) == iro_Cmp))
+      /* The Eor negates a Cmp. The Cmp has the negated result anyways! */
+      n = new_r_Proj(current_ir_graph, get_nodes_Block(n), get_Proj_pred(a),
+                     mode_b, get_negated_pnc(get_Proj_proj(a)));
+    else if (   (get_irn_mode(n) == mode_b)
+            && (tarval_classify (computed_value (b)) == 1))
+      /* The Eor is a Not. Replace it by a Not. */
+      /*   ????!!!Extend to bitfield 1111111. */
+      n = new_r_Not(current_ir_graph, get_nodes_Block(n), a, mode_b);
+  }
+  break;
+  case iro_Not: {
+    a = get_Not_op(n);
+
+    if (   (get_irn_mode(n) == mode_b)
+       && (get_irn_op(a) == op_Proj)
+        && (get_irn_mode(a) == mode_b)
+       && (get_irn_op(get_Proj_pred(a)) == iro_Cmp))
+      /* We negate a Cmp. The Cmp has the negated result anyways! */
+      n = new_r_Proj(current_ir_graph, get_nodes_Block(n), get_Proj_pred(a),
+                     mode_b, get_negated_pnc(get_Proj_proj(a)));
+  }
+  break;
+  default: ;
+  }
+}
+#endif
+
+/***************** Common Subexpression Elimination *****************/
+
+/* Compare function for two nodes in the hash table.   Gets two     */
+/* nodes as parameters.                                             */
+/* @@@  a+b != b+a ? */
+static int
+vt_cmp (const void *elt, const void *key)
+{
+  ir_node *a, *b;
+  int i;
+
+  a = (void *)elt;
+  b = (void *)key;
+
+  if (a == b) return 0;
+
+  if ((get_irn_op(a) != get_irn_op(b)) ||
+      (get_irn_mode(a) != get_irn_mode(b))) return 1;
+
+  /* compare if a's in and b's in are equal */
+  /* GL: we optimize only nodes with in arrays of fixed sizes.
+  if (get_irn_arity (a) != -2) {
+    ins = get_irn_arity (a);
+    if (ins != get_irn_arity (b)) return 1;
+    ain = get_irn_in (a);
+    bin = get_irn_in (b);
+  }
+  */
+  if (get_irn_arity (a) != get_irn_arity(b))
+    return 1;
+
+  /* compare a->in[0..ins] with b->in[0..ins], i.e., include the block. */
+  // do if (*ain++ != *bin++) return 1; while (ins--);
+  for (i = -1; i < get_irn_arity(a); i++)
+    if (get_irn_n(a, i) != get_irn_n(b, i))
+      return 1;
+
+
+  switch (get_irn_opcode(a)) {
+  case iro_Const:
+    return get_irn_const_attr (a) != get_irn_const_attr (b);
+  case iro_Proj:
+    return get_irn_proj_attr (a) != get_irn_proj_attr (b);
+  case iro_Alloc:
+    return (get_irn_alloc_attr(a).where != get_irn_alloc_attr(b).where)
+      || (get_irn_alloc_attr(a).type != get_irn_alloc_attr(b).type);
+  case iro_Free:
+    return (get_irn_free_attr(a) != get_irn_free_attr(b));
+  case iro_SymConst:
+    return (get_irn_symconst_attr(a).num != get_irn_symconst_attr(b).num)
+      || (get_irn_symconst_attr(a).tori.typ != get_irn_symconst_attr(b).tori.typ);
+  case iro_Call:
+    return (get_irn_call_attr(a)->kind != get_irn_call_attr(b)->kind)
+      || (get_irn_call_attr(a)->arity != get_irn_call_attr(b)->arity);
+  case iro_Sel:
+    return (get_irn_sel_attr(a).ent->kind != get_irn_sel_attr(b).ent->kind)
+      || (get_irn_sel_attr(a).ent->name != get_irn_sel_attr(b).ent->name)
+      || (get_irn_sel_attr(a).ent->owner != get_irn_sel_attr(b).ent->owner)
+      || (get_irn_sel_attr(a).ent->ld_name != get_irn_sel_attr(b).ent->ld_name)
+      || (get_irn_sel_attr(a).ent->type != get_irn_sel_attr(b).ent->type)
+      || (get_irn_sel_attr(a).ltyp != get_irn_sel_attr(b).ltyp);
+  case iro_Phi:
+    return get_irn_phi_attr (a) != get_irn_phi_attr (b);
+  default: ;
+  }
+
+  return 0;
+}
+
+static unsigned
+ir_node_hash (ir_node *node)
+{
+  unsigned h;
+  int i;
+
+  // hash table value = 9*(9*(9*(9*(9*arity+in[0])+in[1])+ ...)+mode)+code
+  h = get_irn_arity(node);
+
+  // consider all in nodes... except the block.
+  for (i = 0;  i < get_irn_arity(node);  i++) {
+    h = 9*h + (unsigned long)get_irn_n(node, i);
+  }
+
+  // ...mode,...
+  h = 9*h + (unsigned long) get_irn_mode (node);
+  // ...and code
+  h = 9*h + (unsigned long) get_irn_op (node);
+
+  return h;
+}
+
+pset *
+new_identities (void)
+{
+  return new_pset (vt_cmp, TUNE_NIR_NODES);
+}
+
+void
+del_identities (pset *value_table)
+{
+  del_pset (value_table);
+}
+
+/* Return the canonical node computing the same value as n.
+   Looks up the node in a hash table. */
+static inline ir_node *
+identify (pset *value_table, ir_node *n)
+{
+  ir_node *o = NULL;
+
+  if (!value_table) return n;
+
+  switch (get_irn_opcode (n)) {
+  case iro_Add:
+  case iro_Mul:
+  case iro_Or:
+  case iro_And:
+  case iro_Eor:
+    {
+      /* for commutative operators perform  a OP b == b OP a */
+      if (get_binop_left(n) > get_binop_right(n)) {
+       ir_node *h = get_binop_left(n);
+       set_binop_left(n, get_binop_right(n));
+       set_binop_right(n, h);
+      }
+    }
+  break;
+  default: break;
+  }
+  o = pset_find (value_table, n, ir_node_hash (n));
+  if (!o) return n;
+
+  return o;
+}
+
+/* Return the canonical node computing the same value as n.
+   Looks up the node in a hash table, enters it in the table
+   if it isn't there yet. */
+static ir_node *
+identify_remember (pset *value_table, ir_node *node)
+{
+  ir_node *o = NULL;
+
+  if (!value_table) return node;
+
+  /* lookup or insert in hash table with given hash key. */
+  o = pset_insert (value_table, node, ir_node_hash (node));
+
+  if (o == node) return node;
+
+  return o;
+}
+
+/* garbage in, garbage out. If a node has a dead input, i.e., the
+   Bad node is input to the node, return the Bad node.  */
+static inline ir_node *
+gigo (ir_node *node)
+{
+  int i;
+  ir_op* op = get_irn_op(node);
+
+  /* Blocks, Phis and Tuples may have dead inputs, e.g., if one of the
+     blocks predecessors is dead. */
+  if ( op != op_Block && op != op_Phi && op != op_Tuple) {
+    for (i = -1; i < get_irn_arity(node); i++) {
+      if (is_Bad(get_irn_n(node, i))) {
+        node = new_Bad();
+        break;
+      }
+    }
+  }
+  return node;
+}
+
+
+/* These optimizations deallocate nodes from the obstack.
+   It can only be called if it is guaranteed that no other nodes
+   reference this one, i.e., right after construction of a node.  */
+ir_node *
+optimize (ir_node *n)
+{
+  tarval *tv;
+  ir_node *old_n = n;
+
+  /* if not optimize return n */
+  if (n == NULL) {
+    printf(" attention: empty node!!! \n");
+    return n;
+  }
+
+  /* constant expression evaluation / constant folding */
+  if (get_opt_constant_folding()) {
+    /* constants can not be evaluated */
+    if  (get_irn_op(n) != op_Const) {
+      /* try to evaluate */
+      tv = computed_value (n);
+      if (tv != NULL) {
+        /* evaluation was succesful -- replace the node. */
+       obstack_free (current_ir_graph->obst, n);
+       return new_Const (get_tv_mode (tv), tv);
+        // xprintf("* optimize: computed node %I\n", n->op->name);
+      }
+    }
+  }
+  /* remove unnecessary nodes */
+  if (get_opt_constant_folding() || get_irn_op(n) == op_Phi)
+    n = equivalent_node (n);
+
+  /** common subexpression elimination **/
+  /* Checks whether n is already available. */
+  /* The block input is used to distinguish different subexpressions.  Right
+     now all nodes are pinned to blocks, i.e., the cse only finds common
+     subexpressions within a block. */
+
+  if (get_opt_cse())
+    n = identify (current_ir_graph->value_table, n);
+
+  /* identify found a cse, so deallocate the old node. */
+  if (n != old_n) {
+    obstack_free (current_ir_graph->obst, old_n);
+    // The AmRoq fiasco returns n here.  Martin's version doesn't.
+  }
+
+#if 0
+  /* Some more constant expression evaluation. */
+  if (get_opt_constant_folding())
+    n = transform_node (n);
+#endif
+
+  /* Remove nodes with dead (Bad) input. */
+  n = gigo (n);
+  /* Now we can verify the node, as it has no dead inputs any more. */
+  ir_vrfy(n);
+
+  /* Now we have a legal, useful node. Enter it in hash table for cse */
+  if (get_opt_cse()) {
+    // aborts ??! set/pset can not handle several hash tables??!
+    // No, suddenly it works.
+    n = identify_remember (current_ir_graph->value_table, n);
+  }
+
+#if 0  // GL: what's the use of this??
+  if ((current_ir_graph->state & irgs_building) && IR_KEEP_ALIVE (n)) {
+    assert (~current_ir_graph->state & irgs_keep_alives_in_arr);
+    pdeq_putr (current_ir_graph->keep.living, n);
+  }
+#endif
+
+  return n;
+}
+
+
+/* These optimizations never deallocate nodes.  This can cause dead
+   nodes lying on the obstack.  Remove these by a dead node elimination,
+   i.e., a copying garbage collection. */
+ir_node *
+optimize_in_place (ir_node *n)
+{
+
+  tarval *tv;
+  ir_node *old_n = n;
+
+  /* if not optimize return n */
+  if (n == NULL) {
+    // Here this is possible.  Why?
+    return n;
+  }
+
+  /* constant expression evaluation / constant folding */
+  if (get_opt_constant_folding()) {
+    /* constants can not be evaluated */
+    if  (get_irn_op(n) != op_Const) {
+      /* try to evaluate */
+      tv = computed_value (n);
+      if (tv != NULL) {
+        /* evaluation was succesful -- replace the node. */
+       return new_Const (get_tv_mode (tv), tv);
+        // xprintf("* optimize: computed node %I\n", n->op->name);
+      }
+    }
+  }
+  /* remove unnecessary nodes */
+  if (get_opt_constant_folding() || get_irn_op(n) == op_Phi)
+    n = equivalent_node (n);
+
+  /** common subexpression elimination **/
+  /* Checks whether n is already available. */
+  /* The block input is used to distinguish different subexpressions.  Right
+     now all nodes are pinned to blocks, i.e., the cse only finds common
+     subexpressions within a block. */
+
+  if (get_opt_cse())
+    n = identify (current_ir_graph->value_table, n);
+
+  /* identify found a cse, so deallocate the old node. */
+  if (n != old_n) {
+    // The AmRoq fiasco returns n here.  Martin's version doesn't.
+  }
+
+#if 0
+  /* Some more constant expression evaluation. */
+  if (get_opt_constant_folding())
+    n = transform_node (n);
+#endif
+
+  /* Remove nodes with dead (Bad) input. */
+  n = gigo (n);
+  /* Now we can verify the node, as it has no dead inputs any more. */
+  ir_vrfy(n);
+
+  /* Now we have a legal, useful node. Enter it in hash table for cse */
+  if (get_opt_cse()) {
+    // aborts ??! set/pset can not handle several hash tables??!
+    // No, suddenly it works.
+    n = identify_remember (current_ir_graph->value_table, n);
+  }
+
+  return n;
+}
+
+
+void
+optimize_in_place_wrapper (ir_node *n, void *env) {
+  int i;
+  ir_node *optimized;
+
+  /* optimize all sons after recursion, i.e., the sons' sons are
+     optimized already. */
+  for (i = -1; i < get_irn_arity(n); i++) {
+    optimized = optimize_in_place(get_irn_n(n, i));
+    set_irn_n(n, i, optimized);
+  }
+}
+
+
+void
+optimize_graph (ir_graph *irg)
+{
+  ir_graph *rem = current_ir_graph;
+  current_ir_graph = irg;
+
+  /* walk over the graph */
+  irg_walk(irg->end, NULL, optimize_in_place_wrapper, NULL);
+
+  current_ir_graph = rem;
+}
diff --git a/ir/ir/iropt.c.flc b/ir/ir/iropt.c.flc
new file mode 100644 (file)
index 0000000..9d8589a
--- /dev/null
@@ -0,0 +1,3 @@
+
+(fast-lock-cache-data 3 (quote (14526 . 42219)) (quote nil) (quote nil) (quote (t ("^\\(\\sw+\\)[      ]*(" (1 font-lock-function-name-face)) ("^#[    ]*error[        ]+\\(.+\\)" (1 font-lock-warning-face prepend)) ("^#[   ]*\\(import\\|include\\)[       ]*\\(<[^>\"
+]*>?\\)" (2 font-lock-string-face)) ("^#[      ]*define[       ]+\\(\\sw+\\)(" (1 font-lock-function-name-face)) ("^#[         ]*\\(elif\\|if\\)\\>" ("\\<\\(defined\\)\\>[    ]*(?\\(\\sw+\\)?" nil nil (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t))) ("^#[     ]*\\(\\sw+\\)\\>[       !]*\\(\\sw+\\)?" (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t)) ("\\<\\(c\\(har\\|omplex\\)\\|double\\|float\\|int\\|long\\|s\\(hort\\|igned\\)\\|unsigned\\|void\\|FILE\\|\\sw+_t\\)\\>" (0 font-lock-type-face)) ("\\<\\(\\(auto\\|break\\|con\\(st\\|tinue\\)\\|do\\|e\\(lse\\|xtern\\)\\|for\\|if\\|re\\(gister\\|strict\\|turn\\)\\|s\\(izeof\\|tatic\\|witch\\)\\|typedef\\|volatile\\|while\\)\\|\\(enum\\|struct\\|union\\)\\)\\>" (0 font-lock-keyword-face)) ("\\<\\(case\\|goto\\)\\>[   ]*\\(-?\\sw+\\)?" (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) (":" ("^[       ]*\\(\\sw+\\)[  ]*:[    ]*$" (beginning-of-line) (end-of-line) (1 font-lock-constant-face))) ("\\<\\(c\\(har\\|omplex\\)\\|double\\|float\\|int\\|long\\|s\\(hort\\|igned\\)\\|unsigned\\|void\\|FILE\\|\\sw+_t\\)\\>\\([       *&]+\\sw+\\>\\)*" (font-lock-match-c-style-declaration-item-and-skip-to-next (goto-char (or (match-beginning 4) (match-end 1))) (goto-char (match-end 1)) (1 (if (match-beginning 2) font-lock-function-name-face font-lock-variable-name-face)))) ("\\<\\(\\(enum\\|struct\\|union\\)\\)\\>[   ]*\\(\\sw+\\)?" (1 font-lock-keyword-face) (3 font-lock-type-face nil t) (font-lock-match-c-style-declaration-item-and-skip-to-next nil nil (1 (if (match-beginning 2) font-lock-function-name-face font-lock-variable-name-face) nil t))) ("\\(}\\)[   *]*\\sw" (font-lock-match-c-style-declaration-item-and-skip-to-next (goto-char (match-end 1)) nil (1 font-lock-type-face))) ("^\\(\\sw+\\)\\>\\([       *]+\\sw+\\>\\)*" (1 font-lock-type-face) (font-lock-match-c-style-declaration-item-and-skip-to-next (goto-char (or (match-beginning 2) (match-end 1))) nil (1 (if (match-beginning 2) font-lock-function-name-face font-lock-variable-name-face)))))) (quote ((font-lock-constant-face 26025 26032 26009 26016 25994 26000 25978 25985 25962 25969 24978 24985 24517 24524 24359 24367 24181 24193 24104 24112 23945 23954 23869 23877 23790 23799 22251 22258 21479 21486 20069 20077 18537 18545 17233 17243 16715 16721 16210 16218 15383 15392 14900 14908 12028 12035 11709 11717 11463 11470 10964 10971 10723 10730 10477 10486 10439 10446 10166 10173 10149 10157 10133 10140 10117 10124 10101 10108 9597 9604 9581 9588 9537 9543 9022 9029 8031 8040 3703 3711 3614 3622 3543 3550 3470 3478 3402 3409 3334 3341 3273 3280 3205 3212 2949 2955 2693 2700 2568 2575 2144 2151 2025 2034 1789 1796 1630 1637 1581 1590) (font-lock-type-face 32062 32066 31802 31805 31787 31791 31742 31746 29917 29924 27581 27588 27010 27013 25628 25632 25571 25575 25548 25552 25507 25511 25498 25506 25441 25445 25432 25440 25371 25375 25362 25370 25140 25143 25126 25134 25084 25092 23040 23044 23021 23025 23006 23009 22973 22977 22956 22960 22938 22941 17251 17254 12271 12274 8673 8676 7620 7623 6797 6801 898 904) (font-lock-function-name-face 32068 32082 31748 31773 29927 29944 27591 27599 26985 26989 26554 26571 25825 25833 25633 25647 25555 25569 25093 25105 22942 22948 17126 17140 7587 7602 6802 6820 907 921 638 646 519 528) (font-lock-variable-name-face 31806 31807 31793 31796 31199 31200 29482 29483 28951 28952 27014 27015 26975 26982 26544 26551 25815 25822 25144 25145 25135 25136 23010 23011 22979 22982 22962 22965 17255 17264 17116 17123 16831 16832 12855 12856 12278 12285 12275 12276 8677 8678 7624 7627 7577 7584 629 635 509 516) (font-lock-keyword-face 31926 31929 31728 31734 31542 31544 31253 31255 31100 31102 30963 30965 30592 30594 30431 30437 30350 30352 30251 30253 30168 30170 30093 30099 30036 30038 29718 29724 29519 29521 29294 29296 29005 29007 28802 28804 28665 28667 28294 28296 28133 28139 28009 28011 27910 27912 27827 27829 27752 27758 27687 27689 27371 27377 27344 27349 27276 27278 27225 27228 27160 27162 26961 26967 26823 26829 26805 26811 26790 26792 26653 26659 26635 26637 26537 26543 26373 26379 26360 26366 26352 26354 26287 26292 26269 26274 26110 26112 26020 26024 26004 26008 25989 25993 25973 25977 25957 25961 25925 25931 25912 25918 25894 25896 25801 25807 25581 25587 25535 25541 25301 25304 25077 25083 25064 25070 24991 24997 24973 24977 24530 24536 24512 24516 24373 24379 24354 24358 24199 24205 24176 24180 24119 24125 24099 24103 23960 23966 23940 23944 23883 23889 23864 23868 23805 23811 23785 23789 23754 23760 23738 23744 23691 23693 23647 23650 23504 23510 23456 23458 23165 23171 23080 23082 23067 23073 23055 23057 22967 22972 22950 22955 22931 22937 22659 22664 22290 22292 22246 22250 22237 22242 21972 21974 21967 21971 21546 21548 21474 21478 21465 21470 21380 21384 21160 21162 21037 21039 20851 20853 20846 20850 20805 20809 20743 20745 20113 20115 20064 20068 20054 20059 19546 19548 19541 19545 19195 19197 19190 19194 19107 19111 18971 18973 18712 18714 18532 18536 18521 18526 18266 18268 18184 18186 18179 18183 18057 18062 18046 18048 17909 17914 17898 17900 17816 17818 17811 17815 17705 17707 17694 17696 17621 17625 17468 17470 17455 17460 17374 17376 17228 17232 17197 17203 17109 17115 16785 16791 16771 16776 16750 16755 16710 16714 16700 16705 16560 16562 16555 16559 16443 16447 16345 16347 16261 16263 16205 16209 16195 16200 15765 15767 15760 15764 15551 15553 15378 15382 15369 15374 15278 15280 15273 15277 15040 15042 14999 15001 14895 14899 14885 14890 14782 14787 14737 14741 14702 14704 14598 14603 14424 14426 14280 14285 14142 14147 14107 14109 13971 13976 13732 13734 13583 13586 13500 13505 13195 13197 13082 13084 12835 12840 12728 12730 12706 12711 12643 12645 12023 12027 12013 12018 11852 11854 11813 11815 11808 11812 11723 11725 11704 11708 11695 11700 11622 11624 11617 11621 11548 11550 11543 11547 11476 11478 11458 11462 11308 11313 11011 11013 10959 10963 10950 10955 10878 10880 10873 10877 10805 10807 10718 10722 10709 10714 10617 10619 10472 10476 10434 10438 10425 10430 10255 10257 10161 10165 10144 10148 10128 10132 10112 10116 10096 10100 10087 10092 10027 10029 9905 9910 9900 9904 9850 9852 9845 9849 9795 9797 9592 9596 9576 9580 9566 9571 9546 9548 9532 9536 9169 9174 9117 9119 9017 9021 9001 9006 8931 8933 8920 8925 8882 8884 8831 8834 8629 8631 8624 8628 8480 8482 8026 8030 7994 8000 7909 7911 7904 7908 7826 7828 7570 7576 7188 7194 7172 7178 7072 7074 6933 6935 6692 6698 6664 6669 6577 6581 5402 5404 5265 5269 5153 5155 5038 5040 4951 4955 4641 4643 4548 4550 3698 3702 3689 3694 3624 3626 3609 3613 3600 3605 3552 3554 3538 3542 3529 3534 3480 3482 3465 3469 3456 3461 3411 3413 3397 3401 3388 3393 3343 3345 3329 3333 3320 3325 3282 3284 3268 3272 3259 3264 3214 3216 3200 3204 3191 3196 3045 3047 3015 3019 2961 2963 2944 2948 2935 2940 2791 2793 2761 2765 2706 2708 2688 2692 2679 2684 2581 2583 2563 2567 2554 2559 2410 2412 2263 2267 2157 2159 2139 2143 2130 2135 2042 2044 2020 2024 2011 2016 1934 1936 1929 1933 1802 1804 1784 1788 1775 1780 1643 1645 1625 1629 1576 1580 1545 1551 1247 1249 1242 1246 1164 1166 755 761 746 750 716 722 664 666 615 621 601 607 546 551 495 501) (string 27715 27745 379 385 357 368 336 346 316 325) (font-lock-builtin-face 31314 31319 31196 31198 29709 29714 29479 29481 29066 29071 28948 28950 22686 22691 16828 16830 13519 13524 12852 12854 371 378 349 356 328 335 308 315) (font-lock-comment-face 32167 32192 31834 31923 31632 31659 31567 31628 31469 31539 31383 31451 31323 31364 31203 31250 31122 31185 31042 31097 30773 30959 30726 30770 30683 30723 30559 30589 30480 30539 30378 30429 30291 30312 30210 30246 30110 30165 30057 30089 30003 30033 29732 29916 29485 29517 29384 29411 29319 29380 29221 29291 29135 29203 29075 29116 28955 29002 28874 28937 28744 28799 28475 28661 28428 28472 28385 28425 28261 28291 28182 28241 28037 28088 27950 27971 27869 27905 27769 27824 27654 27684 27388 27580 27052 27157 26836 26960 26669 26726 26386 26536 26046 26103 25699 25800 25470 25485 25403 25419 25253 25299 25150 25223 23592 23645 23517 23589 23225 23453 23178 23222 22907 22930 22836 22906 22765 22835 22693 22763 22448 22510 22118 22160 22067 22111 21752 21820 21395 21421 21182 21210 21097 21151 20990 21030 20415 20467 20231 20333 19821 19944 19618 19670 19242 19462 18995 19034 18759 18874 18553 18631 18283 18305 18064 18087 17916 17997 16833 17108 16797 16824 16634 16665 16471 16524 16303 16343 15941 16070 15899 15930 15677 15743 15398 15429 15286 15333 15099 15223 14750 14779 14632 14695 14362 14377 14182 14273 14057 14100 14002 14031 13940 13967 13860 13880 13783 13805 13676 13691 13533 13576 12909 13075 12863 12902 12803 12834 12748 12794 12581 12636 12426 12445 12373 12392 12320 12339 12049 12264 11952 11994 11765 11788 11500 11538 11319 11454 11087 11128 11060 11080 10977 11006 10736 10800 10504 10612 10488 10502 10450 10469 10323 10414 10179 10250 9919 10020 9649 9788 9457 9529 9178 9452 9078 9112 9032 9073 8682 8828 8337 8473 8258 8330 8054 8214 7962 7991 7785 7823 7732 7751 7691 7710 7650 7669 7202 7569 6729 6796 6707 6725 6592 6646 6473 6482 6110 6143 5875 5898 5643 5668 5414 5448 5273 5292 5078 5101 5056 5065 4677 4880 4657 4666 3778 4541 3567 3596 3495 3525 3291 3316 2631 2673 2601 2621 2276 2386 2171 2221 2098 2120 1490 1542 1297 1444 1105 1161 1054 1086 988 1020 772 897 387 494 1 304))))
diff --git a/ir/ir/iropt.h b/ir/ir/iropt.h
new file mode 100644 (file)
index 0000000..7f1389d
--- /dev/null
@@ -0,0 +1,39 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+** Declarations for optimizations intertwined with IR construction.
+*/
+
+# ifndef _IROPT_H_
+# define _IROPT_H_
+
+# include "irnode.h"
+# include "irgraph.h"
+# include "irflag.h"
+# include "pset.h"
+# include "tune.h"
+
+/* optimize_in_place (n) may change the contents of the ir_node itself,
+   [e.g. by making it a Id-node], but does not change its identity.
+   So it is safe to be called on already referenced nodes.
+
+   optimize_in_place (n) returns a pointer to a node equivalent to `n'
+   which should be used instead of `n'.
+
+   optimize (n) may deallocate `n' and everything allocated after `n'! */
+
+tarval *computed_value (ir_node *n);
+
+pset *new_identities (void);
+void del_identities (pset *value_table);
+
+ir_node *optimize (ir_node *n);
+ir_node *optimize_in_place (ir_node *n);
+
+
+void optimize_graph (ir_graph *irg);
+
+
+# endif /* _IROPT_H_ */
diff --git a/ir/ir/irvrfy.c b/ir/ir/irvrfy.c
new file mode 100644 (file)
index 0000000..36ce229
--- /dev/null
@@ -0,0 +1,336 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer
+**
+**
+*/
+
+# include "irvrfy.h"
+# include "irgwalk.h"
+
+void
+ir_vrfy (ir_node *n)
+{
+  int i;
+  int opcode;
+  ir_mode *mymode, *op1mode, *op2mode, *op3mode;
+  int op_is_symmetric = 1;     /* 0: asymmetric
+                                  1: operands have identical modes
+                                  2: modes of operands == mode of this node */
+
+  ir_node **in;
+
+  opcode = get_irn_opcode (n);
+  mymode = get_irn_mode (n);
+  in = get_irn_in (n);
+
+//  IR_OP_VRFY (opcode);
+//  IR_MODE_VRFY (mymode);
+
+  switch (opcode) {
+
+  case iro_Start:
+    assert (
+           /* Start: BB --> X x M x P x data1 x ... x datan */
+           mymode == mode_T
+          );
+    break;
+  case iro_Jmp:
+    assert (
+           /* Jmp: BB --> X */
+           mymode == mode_X
+          );
+    break;
+  case iro_Cond:
+    op1mode = get_irn_mode(in[1]);
+    assert (
+           /* Cond: BB x b --> X x X */
+           (op1mode == mode_b
+           /* Cond: BB x Iu --> X^n */
+           || op1mode == mode_I)
+           );
+            assert (mymode == mode_T);
+    break;
+  case iro_Return:
+    op1mode = get_irn_mode(in[1]);
+      /* Return: BB x M x data1 x ... x datan --> X */
+    //printf("mode: %s, code %s\n", ID_TO_STR(n->mode->name), ID_TO_STR(n->op->name));
+    assert ( op1mode == mode_M );  /* operand M */
+    for (i=2; i < get_irn_arity(n); i++) {
+      assert ( mode_is_data(get_irn_mode(in[i])) );  /* operand datai */
+    };
+    assert ( mymode == mode_X );   /* result X */
+    break;
+  case iro_Raise:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert (
+           /* Sel: BB x M x P --> X x M */
+           op1mode == mode_M && op2mode == mode_p
+           && mymode == mode_T
+          );
+    break;
+  case iro_Const:
+    assert (
+           /* Const: BB --> data */
+           mode_is_data (mymode) ||
+            mymode == mode_b      /* we want boolean constants for static evaluation
+                                     of Cmp. */
+          );
+    break;
+  case iro_SymConst:
+    assert (
+           /* SymConst: BB --> Iu or
+                         BB --> P */
+           (mymode == mode_I) || (mymode == mode_p)
+          );
+    break;
+  case iro_Sel:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert (
+           /* Sel: BB x M x P x Iu^n --> P */
+           op1mode == mode_M && op2mode == mode_p
+            && mymode == mode_p
+          );
+    for (i=3; i < get_irn_arity(n); i++) {
+           assert (get_irn_mode(in[i]) == mode_I); }
+    break;
+  case iro_Call:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+      /* Call: BB x M x P x data1 x ... x datan
+                 --> M x datan+1 x ... x data n+m */
+    assert ( op1mode == mode_M && op2mode == mode_p );  /* operand M x P */
+    for (i=3; i < get_irn_arity(n); i++) {
+      assert ( mode_is_data(get_irn_mode(in[i])) );  /* operand datai */
+    };
+    assert ( mymode == mode_T );   /* result T */
+    break;
+  case iro_Add:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert (
+           /* common Add: BB x num x num --> num */
+           (mymode == op1mode && mymode == op2mode
+             && mode_is_num(mymode))
+           ||  /* Pointer Add: BB x P x Is --> P */
+           (op1mode == mode_p && op2mode == mode_i && mymode == mode_p)
+           ||  /* Pointer Add: BB x Is x P --> P */
+           (op1mode == mode_i && op2mode == mode_p && mymode == mode_p)
+           );
+      if (op1mode == mode_p || op2mode == mode_p) {
+       /* BB x P x Is --> P or BB x Is x P --> P */
+        op_is_symmetric = 0; /* ArmRoq */
+      } else {
+       /* BB x num x num --> num */
+        op_is_symmetric = 2;
+      }
+    break;
+  case iro_Sub:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert (
+           /* common Sub: BB x num x num --> num */
+           (mymode ==op1mode && mymode == op2mode
+            && mode_is_num(op1mode))
+           ||  /* Pointer Sub: BB x P x Is --> P */
+           (op1mode == mode_p && op2mode == mode_i && mymode == mode_p)
+           ||  /* Pointer Sub: BB x Is x P --> P */
+           (op1mode == mode_i && op2mode == mode_p && mymode == mode_p)
+           ||  /* Pointer Sub: BB x P x P --> Is */
+           (op1mode == mode_p && op2mode == mode_p && mymode == mode_i)
+           );
+      if (op1mode == mode_p && op2mode == mode_p) {
+        op_is_symmetric = 1; /* ArmRoq */
+      } else if (op1mode == mode_p || op2mode == mode_p) {
+        op_is_symmetric = 0; /* ArmRoq */
+      } else {
+        op_is_symmetric = 2;
+      }
+    break;
+  case iro_Minus:
+    op1mode = get_irn_mode(in[1]);
+    assert (
+           /* Minus: BB x float --> float */
+           op1mode == mymode && mode_is_float (op1mode)
+          );
+    op_is_symmetric = 2;
+    break;
+  case iro_Mul:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert (
+           /* Mul: BB x num x num --> num */
+           mymode == op1mode && mymode == op2mode
+           && mode_is_num (op1mode)
+          );
+    op_is_symmetric = 2;
+    break;
+  case iro_Quot:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    op3mode = get_irn_mode(in[3]);
+    assert (
+           /* Quot: BB x M x float x float --> M x X x float */
+           op1mode == mode_M && op2mode == op3mode
+           && mode_is_float(op2mode) && mymode == mode_T
+          );
+    op_is_symmetric = 2;
+    break;
+  case iro_DivMod:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    op3mode = get_irn_mode(in[3]);
+    assert (
+           /* DivMod: BB x M x num x num --> M x X x Is x Is */
+           op1mode == mode_M && op2mode == op3mode
+           && mode_is_num (op2mode) && mymode == mode_T
+           );
+    op_is_symmetric = 1;
+    break;
+  case iro_Div:
+  case iro_Mod:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    op3mode = get_irn_mode(in[3]);
+    assert (
+           /* Div or Mod: BB x M x num x num --> M x X x Is */
+           op1mode == mode_M && op2mode == op3mode &&
+           mode_is_num (op2mode) && mymode == mode_T
+           );
+    op_is_symmetric = 1;
+    break;
+  case iro_Abs:
+    op1mode = get_irn_mode(in[1]);
+    assert (
+           /* Abs: BB x num --> num */
+           op1mode == mymode && mode_is_num (op1mode)
+          );
+    op_is_symmetric = 2;
+    break;
+  case iro_And:
+  case iro_Or:
+  case iro_Eor:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert(
+          /* And or Or or Eor: BB x int x int --> int */
+          mymode == op1mode && mymode == op2mode
+          && mode_is_int (mymode)
+         );
+    op_is_symmetric = 2;
+    break;
+  case iro_Not:
+    op1mode = get_irn_mode(in[1]);
+    assert(
+          /* Not: BB x int --> int */
+          mymode == op1mode
+          && mode_is_int (mymode)
+         );
+    op_is_symmetric = 2;
+    break;
+
+  case iro_Cmp:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert(
+          /* Cmp: BB x datab x datab --> b16 */
+           op1mode == op2mode && mode_is_data (op1mode)
+           && mymode == mode_T
+         );
+    break;
+  case iro_Shl:
+  case iro_Shr:
+  case iro_Shrs:
+  case iro_Rot:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert(
+          /* Shl, Shr, Shrs or Rot: BB x int x Iu --> int */
+          mode_is_int (op1mode) && op2mode == mode_I
+           && op1mode == mymode
+         );
+    break;
+  case iro_Conv:
+    op1mode = get_irn_mode(in[1]);
+    assert(
+           /* Conv: BB x datab1 --> datab2 */
+          mode_is_datab (op1mode)
+           && mode_is_data (mymode)
+         );
+    break;
+  case iro_Phi:
+           /* Phi: BB x dataM^n --> dataM */
+    /* for some reason "<=" aborts. Is there a problem with get_store? */
+    for (i=1; i < get_irn_arity(n); i++) {
+      assert ( get_irn_mode(in[i]) == mymode );
+    };
+    assert ( mode_is_dataM(mymode) );
+    break;
+  case iro_Load:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert(
+           /* Load: BB x M x P --> M x X x data */
+           op1mode == mode_M && op2mode == mode_p
+         );
+    assert ( mymode == mode_T );
+    break;
+  case iro_Store:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    op3mode = get_irn_mode(in[3]);
+    assert(
+           /* Load: BB x M x P x data --> M x X */
+           op1mode == mode_M && op2mode == mode_p
+           && mode_is_data (op3mode)
+         );
+    assert(mymode == mode_T);
+    break;
+  case iro_Alloc:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    assert(
+           /* Alloc: BB x M x Iu --> M x X x P */
+           op1mode == mode_M && op2mode == mode_I
+           && mymode == mode_T
+         );
+    break;
+  case iro_Free:
+    op1mode = get_irn_mode(in[1]);
+    op2mode = get_irn_mode(in[2]);
+    op3mode = get_irn_mode(in[3]);
+    assert(
+           /* Free: BB x M x P x Iu --> M */
+           op1mode == mode_M && op2mode == mode_p && op3mode == mode_I
+           && mymode == mode_M
+         );
+    break;
+  case iro_Sync:
+           /* Sync: BB x M^n --> M */
+    for (i=1; i < get_irn_arity(n); i++) {
+      assert ( get_irn_mode(in[i]) == mode_M );
+    };
+    assert ( mymode == mode_M );
+    break;
+
+  default: ;
+  }
+}
+
+/*******************************************************************/
+/* Verify the whole graph.                                         */
+/*******************************************************************/
+
+void
+vrfy_wrap (ir_node *node, void *env) {
+  ir_vrfy(node);
+}
+
+void
+vrfy_graph (ir_graph *irg)
+{
+  irg_walk(irg->end, vrfy_wrap, NULL, NULL);
+}
diff --git a/ir/ir/irvrfy.h b/ir/ir/irvrfy.h
new file mode 100644 (file)
index 0000000..9ec0740
--- /dev/null
@@ -0,0 +1,22 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Author: Christian Schaefer
+**
+** irgraph.h: ir graph verification
+*/
+
+# ifndef _IRVRFY_H_
+# define _IRVRFY_H_
+
+# include "irnode.h"
+# include "irgraph.h"
+
+/* Tests the types of predecessors of checknode. */
+void ir_vrfy (struct ir_node *checknode);
+
+/* Calls ir_vrfy for each node in irg. */
+void vrfy_graph (ir_graph *irg);
+
+
+# endif /* _IRVRFY_H_ */
diff --git a/ir/tr/Makefile b/ir/tr/Makefile
new file mode 100644 (file)
index 0000000..aaf3ae2
--- /dev/null
@@ -0,0 +1,62 @@
+# Hey, emacs, this is a -*- makefile -*-
+#
+# Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Makefile for tr -- the type representation
+
+CXX         = gcc
+CFLAGS      = -pipe -Wall # -ansi -pedantic
+CXXFLAGS    = # -g
+COPTFLAGS   = -O3
+LDFLAGS     =
+DEPENDFLAGS = -M
+LIBPATH     =
+LIBS        =
+X_LIBS      =
+INCLUDES    = -I../adt -I../common -I../debug -I../ident -I../include \
+             -I../ir -I../tr -I../tv
+X_INCLUDES  =
+
+SHELL       = /bin/sh
+MAKE        = /usr/bin/make
+
+MEMBERS         = entity.m mangle.m type.m typewalk.m
+
+CFILES = $(MEMBERS:.m=.c)
+
+HFILES = $(MEMBERS:.m=.h)
+HFILES +=  type_or_entity.h
+HFILES +=  common.h debug.h gmp.h host.h ident.h irgraph.h  \
+           irgwalk.h irmode.h irnode.h irop.h label.h misc.h \
+           obst.h pset.h set.h tv.h xprintf.h xp_help.h
+
+OFILES = $(MEMBERS:%.m=../objects/%.o)
+
+DFILES = $(MEMBERS:.m=.d)
+
+TARGET = all
+
+.PHONY: default all clean realclean install depend
+.SUFFIXES: .d .h .c .o
+.DEFAULT: $(TARGET)
+.SILENT: $(DFILES) clean  # hides output
+
+%.d:    %.c
+       $(SHELL) -ec '$(CXX) $(DEPENDFLAGS) $(INCLUDES) $(X_INCLUDES) $< | sed '\''s/\($*\)\.o[ :]*/\.\.\/objects\/\1.o $@ : /g'\'' > $@'
+
+
+../objects/%.o:    %.c
+       $(CXX) $(CFLAGS) $(CXXFLAGS) $(COPTFLAGS) $(INCLUDES) $(X_INCLUDES) -c $< -o $@
+
+
+$(TARGET):      $(DFILES) $(OFILES)
+
+clean:
+       rm -f $(OFILES) $(DFILES)
+
+realclean:     clean
+       rm -f $(TARGET) *.flc TAGS
+
+-include $(DFILES)
diff --git a/ir/tr/TYPE_REPRESENTATION b/ir/tr/TYPE_REPRESENTATION
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ir/tr/entity.c b/ir/tr/entity.c
new file mode 100644 (file)
index 0000000..12466f4
--- /dev/null
@@ -0,0 +1,103 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# include <stdlib.h>
+# include "entity.h"
+# include "mangle.h"
+
+/*******************************************************************/
+/** general                                                       **/
+/*******************************************************************/
+
+void
+init_entity (void)
+{
+}
+
+/*******************************************************************/
+/** ENTITY                                                        **/
+/*******************************************************************/
+
+entity *
+// new_entity (type_class *owner, ident *name, type *type)
+new_entity (type *owner, ident *name, type *type)
+{
+  entity *res;
+
+  res = (entity *) malloc (sizeof (entity));
+  res->kind = k_entity;
+  assert_legal_owner_of_ent(owner);
+  res->owner = owner;
+  res->name = name;
+  res->type = type;
+  res->ld_name = NULL;
+
+  res->visit = 0;
+
+  /* add entity to the list of entities of the owner. */
+  // res->owner->member[res->owner->n_members] = res;
+  // res->owner->n_members ++;
+
+  return res;
+}
+
+/*
+  char  *get_entity_name     (entity *);  */
+
+ident *
+get_entity_ident    (entity *ent) {
+  assert(ent);
+  return ent->name;
+}
+/*
+void   set_entity_ld_name  (entity *, char *ld_name);
+void   set_entity_ld_ident (entity *, ident *ld_ident);
+*/
+
+//inline type_class *
+inline type *
+get_entity_owner (entity *entity) {
+  return entity->owner;
+}
+
+inline void
+// set_entity_owner (entity *entity, type_class *owner) {
+set_entity_owner (entity *entity, type *owner) {
+  assert_legal_owner_of_ent(owner);
+  entity->owner = owner;
+}
+
+inline void   /* should this go into type.c? */
+assert_legal_owner_of_ent(type *type) {
+  assert (type->clss.kind   == k_type_class ||
+          type->uni.kind    == k_type_union ||
+          type->array.kind  == k_type_array ||
+          type->method.kind == k_type_method );
+}
+
+inline ident *
+get_entity_ld_name (entity *ent)
+{
+  if (ent->ld_name != NULL) return ent->ld_name;
+  return mangle_entity (ent);
+}
+
+/*
+char  *get_entity_ld_name  (entity *);
+void   set_entity_ld_name  (entity *, char *ld_name);
+void   set_entity_ld_ident (entity *, ident *ld_ident);
+*/
+
+inline type *
+get_entity_type (entity *entity) {
+  return entity->type;
+}
+
+inline void
+set_entity_type (entity *entity, type *type) {
+  entity->type = type;
+}
diff --git a/ir/tr/entity.h b/ir/tr/entity.h
new file mode 100644 (file)
index 0000000..57d9e98
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer,
+**          Goetz Lindenmaier
+**
+** entity.h: declarations for entity
+*/
+
+# ifndef _ENTITY_H_
+# define _ENTITY_H_
+
+# include "ident.h"
+# include "type.h"
+
+/*******************************************************************/
+/** general                                                       **/
+/*******************************************************************/
+
+/* initalize entity */
+void init_entity (void);
+
+
+/*******************************************************************/
+/** ENTITY                                                        **/
+/*******************************************************************/
+
+typedef struct entity {
+  firm_kind kind;
+  ident *name;          /* name of this entity */
+  // type_class *owner;    /* The class this entity belongs to */
+  type *owner;          /* The class this entity belongs to */
+  ident *ld_name;       // don't know what this is good for.
+  type *type;           /* The type of this entity, e.g., a method type, a
+                           basic type of the language or a class itself */
+  unsigned long visit;  /* visited counter for walks of the type information */
+} entity;
+
+/* create a new entity */
+entity      *new_entity (/*type_class *owner,*/ type *owner,
+                         ident *name, type *type);
+
+/* manipulate fields of entity */
+/*
+  char        *get_entity_name     (entity *);  */
+ident       *get_entity_ident    (entity *);
+/*
+void         set_entity_ld_name  (entity *, char *ld_name);
+void         set_entity_ld_ident (entity *, ident *ld_ident);
+*/
+
+// type_class *get_entity_owner (entity *);
+type  *get_entity_owner (entity *);
+// void  set_entity_owner (entity *, union type *);
+void   set_entity_owner (entity *, type *);
+inline void  assert_legal_owner_of_ent(type *);
+
+ident *get_entity_ld_name  (entity *); /** resolve name conflict!! standard: ident **/
+/*
+char        *get_entity_ld_ident (entity *);
+void         set_entity_ld_name  (entity *, char *ld_name);
+void         set_entity_ld_ident (entity *, ident *ld_ident);
+*/
+
+type  *get_entity_type (entity *);
+void         set_entity_type (entity *, type *);
+
+# endif /* _ENTITY_H_ */
diff --git a/ir/tr/mangle.c b/ir/tr/mangle.c
new file mode 100644 (file)
index 0000000..9c986a1
--- /dev/null
@@ -0,0 +1,55 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# include "mangle.h"
+# include <obstack.h>
+# include "obst.h"
+# include "entity.h"
+# include <stdlib.h>
+
+static struct obstack mangle_obst;
+
+ident *
+mangle_entity (entity *ent)
+{
+  ident *type_id;
+  char *cp;
+  int len;
+  ident *res;
+
+  type_id = mangle_type ((type *) ent->owner);
+  xoprintf (&mangle_obst, "%I_%I", type_id, ent->name);
+  len = obstack_object_size (&mangle_obst);
+  cp = obstack_finish (&mangle_obst);
+  res = id_from_str (cp, len);
+  obstack_free (&mangle_obst, cp);
+  return res;
+}
+
+ident *
+mangle_type (type *type)
+{
+  char *cp;
+  int len;
+  ident *res;
+
+  assert (type->kind == k_type_class);
+
+  xoprintf (&mangle_obst, "%I", type->clss.name);
+  len = obstack_object_size (&mangle_obst);
+  cp = obstack_finish (&mangle_obst);
+  res = id_from_str (cp, len);
+  obstack_free (&mangle_obst, cp);
+  return res;
+}
+
+
+void
+init_mangle (void)
+{
+  obstack_init (&mangle_obst);
+}
diff --git a/ir/tr/mangle.h b/ir/tr/mangle.h
new file mode 100644 (file)
index 0000000..c1f1b33
--- /dev/null
@@ -0,0 +1,16 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# include "ident.h"
+# include "entity.h"
+# include "type.h"
+
+
+void init_mangle (void);
+
+ident *mangle_entity (entity *ent);
+ident *mangle_type (type *type);
diff --git a/ir/tr/type.c b/ir/tr/type.c
new file mode 100644 (file)
index 0000000..df576af
--- /dev/null
@@ -0,0 +1,509 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer &
+**          Goetz Lindenmaier
+**
+** type.c: datastructures to hold type information.
+*/
+
+# include "type.h"
+
+unsigned long type_visited = 0;
+
+void
+init (void)
+{
+}
+
+/*******************************************************************/
+/** TYPE_CLASS                                                    **/
+/*******************************************************************/
+
+type_class *
+new_type_class (ident *name)//, int members)
+{
+  type_class *res;
+
+  res = (type_class *) xmalloc (sizeof (type_class));
+  res->kind = k_type_class;
+  res->name = name;
+
+  // res->n_members = 0;
+  // res->max_members = members;
+  // res->member = (entity **) xmalloc (sizeof (entity*) * members);
+
+  res->visit = 0;
+
+  return res;
+}
+
+/* manipulate fields of type_class */
+/*
+char  *
+get_class_name  (type_class *class) {
+  assert(class);
+  return ID_TO_STR(class->name);
+}
+*/
+
+ident *
+get_class_ident (type_class *class) {
+  assert(class);
+  return class->name;
+}
+
+/*
+void   set_class_name  (type_class *class, char *name);
+void   set_class_ident (type_class *class, ident* ident);
+*/
+
+
+/*******************************************************************/
+/** TYPE_STRCT                                                   **/
+/*******************************************************************/
+
+type_strct *
+new_type_strct (ident *name)//, int members)
+{
+  type_strct *res;
+
+  res = (type_strct *) xmalloc (sizeof (type_strct));
+  res->kind = k_type_strct;
+  res->name = name;
+
+  // res->n_members = 0;
+  // res->max_members = members;
+  // res->member = (entity **) xmalloc (sizeof (entity*) * members);
+
+  res->visit = 0;
+
+  return res;
+}
+
+/* manipulate fields of type_strct */
+/*
+char  *
+get_strct_name  (type_strct *strct) {
+  assert(strct);
+  return ID_TO_STR(strct->name);
+}
+*/
+
+ident *
+get_strct_ident (type_strct *strct) {
+  assert(strct);
+  return strct->name;
+}
+
+/*
+void   set_strct_name  (type_strct *strct, char *name);
+void   set_strct_ident (type_strct *strct, ident* ident);
+*/
+
+
+/*******************************************************************/
+/** TYPE_METHOD                                                   **/
+/*******************************************************************/
+
+/* create a new type_method */
+type_method *
+new_type_method (ident *name, int arity, int n_res)
+{
+  type_method *res;
+
+  res = (type_method *) xmalloc (sizeof (type_method));
+  res->kind = k_type_method;
+  res->name = name;   // do I need the name, or is the name in entity sufficient?
+  res->arity = arity;
+  res->param_type = (type **) xmalloc (sizeof (type *) * arity);
+  res->n_res  = n_res;
+  res->res_type = (type **) xmalloc (sizeof (type *) * n_res);
+
+  res->visit = 0;
+
+  return res;
+}
+
+/* manipulate fields of type_method */
+/*
+char *
+get_method_name  (type_method *method) {
+  assert(method);
+  return ID_TO_STR(method->name);
+}
+*/
+
+ident *
+get_method_ident (type_method *method) {
+  assert(method);
+  return method->name;
+}
+
+/*
+void   set_method_name  (type_method *method, char *name);
+void   set_method_ident (type_method *method, ident* ident);
+*/
+
+inline int
+get_method_arity (type_method *method) {
+  return method->arity;
+}
+
+/*
+inline void
+set_method_arity (type_method *method, int arity) {
+  method->arity = arity;
+  / change array size, somehow copy.  *
+}
+*/
+
+inline type *
+get_method_param_type(type_method *method, int pos) {
+  return method->param_type[pos];
+}
+
+inline void
+set_method_param_type(type_method *method, int pos, type* type) {
+  method->param_type[pos] = type;
+}
+
+
+inline int
+get_method_n_res (type_method *method) {
+  return method->n_res;
+}
+
+/*
+inline void
+set_method_n_res (type_method *method, int n_res) {
+  method->n_res = n_res;
+}
+*/
+
+inline type *
+get_method_res_type(type_method *method, int pos) {
+  return method->res_type[pos];
+}
+
+inline void
+set_method_res_type(type_method *method, int pos, type* type) {
+  method->res_type[pos] = type;
+}
+
+
+/*******************************************************************/
+/** TYPE_UNION                                                    **/
+/*******************************************************************/
+
+/* create a new type_union -- set unioned types by hand. */
+type_union *
+new_type_union (ident *name, int n_types)
+{
+  type_union *res;
+
+  res = (type_union *) xmalloc (sizeof (type_union));
+  res->kind = k_type_union;
+  res->name = name;   // do I need a name?
+  res->n_types = n_types;
+  /*
+  res->unioned_type = (int *) xmalloc (sizeof (int) * n_types);
+  */
+
+  res->visit = 0;
+
+  return res;
+}
+
+/* manipulate fields of type_union */
+/*
+char *
+get_union_name  (type_union *uni) {
+  assert(uni);
+  return ID_TO_STR(uni->name);
+}
+*/
+
+ident *
+get_union_ident (type_union *uni) {
+  assert(uni);
+  return uni->name;
+}
+
+/*
+void   set_union_name  (type_union *union, char *name);
+void   set_union_ident (type_union *union, ident* ident);
+*/
+/*
+int    get_union_n_types (type_union *union);
+void   set_union_n_types (type_union *union, int n);
+type  *get_union_unioned_type (type_union *union, int pos);
+void   set_union_unioned_type (type_union *union, int pos, type *type);
+*/
+
+/*******************************************************************/
+/** TYPE_ARRAY                                                    **/
+/*******************************************************************/
+
+/* create a new type_array */
+inline type_array *
+new_type_array (ident *name, int n_dimensions)
+{
+  type_array *res;
+
+  res = (type_array *) xmalloc (sizeof (type_array));
+  res->kind = k_type_array;
+  res->name = name;
+  res->n_dimensions = n_dimensions;
+  res->lower_bound = (int *) xmalloc (sizeof (int) * n_dimensions);
+  res->upper_bound = (int *) xmalloc (sizeof (int) * n_dimensions);
+
+  res->visit = 0;
+
+  return res;
+}
+
+/* manipulate fields of type_array */
+/*
+char *
+get_array_name  (type_array *array) {
+  assert(array);
+  return ID_TO_STR(array->name);
+}
+*/
+
+ident *
+get_array_ident (type_array *array) {
+  assert(array);
+  return array->name;
+}
+
+/*
+void   set_array_name  (type_array *array, char *name);
+void   set_array_ident (type_array *array, ident* ident);
+*/
+
+inline void
+set_array_dimensions (type_array* array, int n) {
+  array->n_dimensions = n;
+}
+
+inline int
+get_array_dimensions (type_array* array) {
+  return array->n_dimensions;
+}
+
+inline void
+set_array_bounds (type_array* array, int dimension, int lower_bound,
+                 int upper_bound) {
+  array->lower_bound[dimension-1] = lower_bound;
+  array->upper_bound[dimension-1] = upper_bound;
+}
+
+inline void
+set_array_lower_bound (type_array* array, int dimension, int lower_bound) {
+  array->lower_bound[dimension-1] = lower_bound;
+}
+
+inline void
+set_array_upper_bound (type_array* array, int dimension, int upper_bound) {
+  array->upper_bound[dimension-1] = upper_bound;
+}
+
+inline int
+get_array_lower_bound (type_array* array, int dimension) {
+  return array->lower_bound[dimension-1];
+}
+
+inline int
+get_array_upper_bound (type_array* array, int dimension) {
+  return array->upper_bound[dimension-1];
+}
+
+inline void set_array_element_type (type_array *array, type *type) {
+  array->element_type = type;
+}
+
+inline type *
+get_array_element_type (type_array *array) {
+  return array->element_type;
+}
+
+
+/*******************************************************************/
+/** TYPE_ENUMERATION                                              **/
+/*******************************************************************/
+
+/* create a new type enumeration -- set the enumerators independently */
+type_enumeration *
+new_type_enumeration (ident *name /* , int n_enums */)
+{
+  type_enumeration *res;
+
+  res = (type_enumeration *) xmalloc (sizeof (type_enumeration));
+  res->kind = k_type_enumeration;
+  res->name = name;
+  /*
+  res->n_enums = n_enums;
+  res->enum = (int *) xmalloc (sizeof (int) * n_enums);
+  */
+
+  res->visit = 0;
+
+  return res;
+}
+
+/* manipulate fields of type_enumeration */
+/*
+char *
+get_enumeration_name  (type_enumeration *enumeration) {
+  assert(enumeration);
+  return ID_TO_STR(enumeration->name);
+}
+*/
+
+ident *
+get_enumeration_ident (type_enumeration *enumeration) {
+  assert(enumeration);
+  return enumeration->name;
+}
+
+/*
+void   set_enumeration_name  (type_enumeration *enumeration, char *name);
+void   set_enumeration_ident (type_enumeration *enumeration, ident* ident);
+*/
+/*
+void     set_enumeration_n_enums (type_enumeration *enumeration, int n);
+int     *get_enumeration_n_enums (type_enumeration *enumeration);
+void     set_enumeration_enum    (type_enumeration *enumeration, int pos,
+                                 ir_node const);
+ir_node *get_enumeration_enum    (type_enumeration *enumeration, int pos);
+*/
+
+
+/*******************************************************************/
+/** TYPE_POINTER                                                  **/
+/*******************************************************************/
+
+/* create a new type pointer */
+type_pointer *
+new_type_pointer (ident *name, type *points_to)
+{
+  type_pointer *res;
+
+  res = (type_pointer *) xmalloc (sizeof (type_pointer));
+  res->kind = k_type_pointer;
+  res->name = name;
+  res->points_to = points_to;
+
+  res->visit = 0;
+
+  return res;
+}
+
+/* manipulate fields of type_pointer */
+/*
+char *
+get_pointer_name  (type_pointer *pointer) {
+  assert(pointer);
+  return ID_TO_STR(pointer->name);
+}
+*/
+
+ident *
+get_pointer_ident (type_pointer *pointer) {
+  assert(pointer);
+  return pointer->name;
+}
+
+/*
+void   set_pointer_name  (type_pointer *pointer, char *name);
+void   set_pointer_ident (type_pointer *pointer, ident* ident);
+*/
+
+inline void
+set_pointer_points_to_type (type_pointer *pointer, type* type) {
+  pointer->points_to = type;
+}
+
+inline type *
+get_pointer_points_to_type (type_pointer *pointer) {
+  return pointer->points_to;
+}
+
+
+/*******************************************************************/
+/** TYPE_PRIMITIVE                                                **/
+/*******************************************************************/
+
+/* create a new type_primitive */
+inline type_primitive *
+new_type_primitive (ident *name, ir_mode *mode)
+{
+  type_primitive *res;
+
+  res = (type_primitive *) xmalloc (sizeof (type_primitive));
+  res->kind = k_type_primitive;
+  res->name = name;
+  res->mode = mode;
+
+  res->visit = 0;
+
+  return res;
+}
+
+/* manipulate fields of type_primitive */
+/*
+
+char  *
+get_primitive_name  (type_primitive *primitive) {
+  assert(primitive);
+  return ID_TO_STR(primitive->name);
+}
+*/
+
+ident *
+get_primitive_ident (type_primitive *primitive) {
+  assert(primitive);
+  return primitive->name;
+}
+/*
+void   set_primitive_name  (type_primitive *primitive, char *name);
+void   set_primitive_ident (type_primitive *primitive, ident* ident);
+*/
+
+inline ir_mode *
+get_primitive_mode (type_primitive *primitive) {
+  return primitive->mode;
+}
+
+inline void
+set_primitive_mode (type_primitive *primitive, ir_mode *mode) {
+  primitive->mode = mode;
+}
+
+
+
+
+/*******************************************************************/
+/**  To manage all different types the same                       **/
+/*******************************************************************/
+
+
+int
+is_type(void *thing) {
+  firm_kind kind;
+
+  kind = get_kind(thing);
+  if (   (kind == k_type_class)
+      || (kind == k_type_strct)
+      || (kind == k_type_method)
+      || (kind == k_type_union)
+      || (kind == k_type_array)
+      || (kind == k_type_enumeration)
+      || (kind == k_type_pointer)
+      || (kind == k_type_primitive))
+    return 1;
+  else
+    return 0;
+}
diff --git a/ir/tr/type.h b/ir/tr/type.h
new file mode 100644 (file)
index 0000000..88c2646
--- /dev/null
@@ -0,0 +1,306 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer &
+**          Goetz Lindenmaier
+**
+** type.h: datastructures to hold type information.
+*/
+
+# ifndef _TYPE_H_
+# define _TYPE_H_
+
+# include "common.h"
+# include "ident.h"
+# include "irmode.h"
+
+/* for recursive type definiton */
+typedef union type type;
+
+/* visited flag to traverse the type information */
+extern unsigned long type_visited;
+
+/*******************************************************************/
+/** TYPE_CLASS                                                    **/
+/*******************************************************************/
+
+typedef struct {
+  firm_kind kind;
+  ident *name;
+  /** needs list with it's entities -- does it really??
+      Entities can be added during their creation.
+  int n_members;
+  entity **member; **/
+  unsigned long visit;     /* visited counter for walks of the type information */
+} type_class;
+
+
+/* create a new type_class */
+type_class *new_type_class (ident *name);
+
+/* manipulate fields of type_class */
+char  *get_class_name  (type_class *clss);
+ident *get_class_ident (type_class *clss);
+/*
+void   set_class_name  (type_class *class, char *name);
+void   set_class_ident (type_class *class, ident* ident);
+*/
+
+/*******************************************************************/
+/** TYPE_STRCT                                                   **/
+/*******************************************************************/
+
+typedef struct {
+  firm_kind kind;
+  ident *name;
+  /** needs list with it's entities -- does it really??
+      Entities can be added during their creation.
+  int n_members;
+  entity **member; **/
+  unsigned long visit;     /* visited counter for walks of the type information */
+} type_strct;
+
+
+/* create a new type_strct */
+type_strct *new_type_strct (ident *name);
+
+/* manipulate fields of type_strct */
+char  *get_strct_name  (type_strct *strct);
+ident *get_strct_ident (type_strct *strct);
+/*
+void   set_strct_name  (type_strct *strct, char *name);
+void   set_strct_ident (type_strct *strct, ident* ident);
+*/
+
+
+/*******************************************************************/
+/** TYPE_METHOD                                                   **/
+/*******************************************************************/
+
+typedef struct {
+  firm_kind kind;
+  ident *name;     // do I need the name, or is the name in entity sufficient?
+  int arity;                   /* number of parameters, better n_params */
+  type **param_type;     /* code generation needs this information.
+                                  Should it be generated by the frontend,
+                                  or does this impose unnecessary work for
+                                  optimizatinos that change the parameters of
+                                  methods? */
+  int n_res;                   /* number of results */
+  type **res_type;
+  /** needs pointer to it's ir_graph ??
+  ir_graph *graph; **/
+  unsigned long visit;     /* visited counter for walks of the type information */
+} type_method;
+
+/* create a new type_method */
+type_method *new_type_method (ident *name, int arity, int n_res);
+
+/* manipulate fields of type_method */
+
+char  *get_method_name  (type_method *method);
+ident *get_method_ident (type_method *method);
+/* GL 9.2.2000: who commened these in?
+   I think it's not safe to have these methods.
+   Please add changes to Changes file.
+void   set_method_name  (type_method *method, char *name);
+void   set_method_ident (type_method *method, ident* ident); */
+
+inline int   get_method_arity (type_method *method);
+inline void  set_method_arity (type_method *method, int arity);
+inline type *get_method_param_type(type_method *method, int pos);
+inline void  set_method_param_type(type_method *method, int pos, type* type);
+
+inline int   get_method_n_res (type_method *method);
+inline void  set_method_n_res (type_method *method, int n_res);
+inline type *get_method_res_type(type_method *method, int pos);
+inline void  set_method_res_type(type_method *method, int pos, type* type);
+
+/*
+ir_graph *get_method_graph(type_method *method);
+void *get_method_graph(type_method *method, ir_graph* graph);
+*/
+
+/*******************************************************************/
+/** TYPE_UNION                                                    **/
+/*******************************************************************/
+
+typedef struct {
+  firm_kind kind;
+  ident *name;             // do I need a name?
+  int n_types;
+  /* type **unioned_type;    ... or something like that? */
+  unsigned long visit;     /* visited counter for walks of the type information */
+} type_union;
+
+/* create a new type_union -- set unioned types by hand. */
+type_union *new_type_union (ident *name, int n_types);
+
+/* manipulate fields of type_union */
+char  *get_union_name  (type_union *uni);
+ident *get_union_ident (type_union *uni);
+/*
+void   set_union_name  (type_union *union, char *name);
+void   set_union_ident (type_union *union, ident* ident);
+*/
+/*
+int    get_union_n_types (type_union *union);
+void   set_union_n_types (type_union *union, int n);
+type  *get_union_unioned_type (type_union *union, int pos);
+void   set_union_unioned_type (type_union *union, int pos, type *type);
+*/
+
+/*******************************************************************/
+/** TYPE_ARRAY                                                    **/
+/*******************************************************************/
+
+/* multidimensional, polyhedric arrays */
+typedef struct {
+  firm_kind kind;
+  ident *name;
+  int n_dimensions;   /* Extend Sel to select from multidimensional arrays.  This  */
+  int *lower_bound;   /* will allow to generate explicit array index computations  */
+  int *upper_bound;   /* by replacing a single FIRM node.  As long as this is not
+                         done create arrays with arrays as elements.  */
+                      /* Should I use tarval? */
+  type *element_type;
+  unsigned long visit;     /* visited counter for walks of the type information */
+} type_array;
+
+/* create a new type array -- set dimension sizes independently */
+type_array *new_type_array (ident *name, int n_dimensions);
+
+/* manipulate fields of type_array */
+char  *get_array_name  (type_array *array);
+ident *get_array_ident (type_array *array);
+/*
+void   set_array_name  (type_array *array, char *name);
+void   set_array_ident (type_array *array, ident* ident);
+*/
+void  set_array_n_dimensions  (type_array *array, int n);
+int   get_array_n_dimensions  (type_array *array);
+
+void  set_array_bounds      (type_array *array, int dimension, int lower_bound,
+                                                              int upper_bound);
+void  set_array_lower_bound (type_array *array, int dimension, int lower_bound);
+void  set_array_upper_bound (type_array *array, int dimension, int upper_bound);
+int   get_array_lower_bound (type_array *array, int dimension);
+int   get_array_upper_bound (type_array *array, int dimension);
+
+void  set_array_element_type (type_array *array, type *type);
+type *get_array_element_type (type_array *array);
+
+/*******************************************************************/
+/** TYPE_ENUMERATION                                              **/
+/*******************************************************************/
+/** Enums are needed to keep debugging information.  They can as well
+    be lowered to integers. **/
+
+typedef struct {
+  firm_kind kind;
+  ident *name;
+  /* int n_enums;
+  ir_node **enum    * Contains all constant nodes that represent a member
+                     of the enum -- enumerators. */
+                    // is ir_node the propper array member?
+  unsigned long visit;     /* visited counter for walks of the type information */
+} type_enumeration;
+
+/* create a new type enumeration -- set the enumerators independently */
+type_enumeration *new_type_enumeration (ident *name /* , int n_enums */);
+
+/* manipulate fields of type_enumeration */
+char  *get_enumeration_name  (type_enumeration *enumeration);
+ident *get_enumeration_ident (type_enumeration *enumeration);
+/*
+void   set_enumeration_name  (type_enumeration *enumeration, char *name);
+void   set_enumeration_ident (type_enumeration *enumeration, ident* ident);
+*/
+/*
+void     set_enumeration_n_enums (type_enumeration *enumeration, int n);
+int     *get_enumeration_n_enums (type_enumeration *enumeration);
+void     set_enumeration_enum    (type_enumeration *enumeration, int pos,
+                                 ir_node const);
+ir_node *get_enumeration_enum    (type_enumeration *enumeration, int pos);
+*/
+
+/*******************************************************************/
+/** TYPE_POINTER                                                  **/
+/*******************************************************************/
+
+typedef struct {
+  firm_kind kind;
+  ident *name;
+  /* ir_mode *mode;      * The mode to be used for this type.
+                            Not here as there might be several pointer types?
+                            A method get_pointer_mode should read a unique,
+                            global variable. */
+  type *points_to;
+  unsigned long visit;     /* visited counter for walks of the type information */
+} type_pointer;
+
+/* create a new type pointer */
+type_pointer *new_type_pointer (ident *name, type *points_to);
+
+/* manipulate fields of type_pointer */
+char  *get_pointer_name  (type_pointer *pointer);
+ident *get_pointer_ident (type_pointer *pointer);
+/*
+void   set_pointer_name  (type_pointer *pointer, char *name);
+void   set_pointer_ident (type_pointer *pointer, ident* ident);
+*/
+void  set_pointer_points_to_type (type_pointer *pointer, type *type);
+type *get_pointer_points_to_type (type_pointer *pointer);
+
+/*******************************************************************/
+/** TYPE_PRIMITIVE                                                **/
+/*******************************************************************/
+
+/* primitive, language-defined types */
+/* What is the type of an entity if it is atomic?  Are alle basic data
+   types classses in Sather? Else this is needed. */
+typedef struct {
+  firm_kind kind;
+  ident *name;
+  ir_mode *mode;       /* The mode to be used for this type */
+  unsigned long visit;     /* visited counter for walks of the type information */
+} type_primitive;
+
+/* create a new type primitive */
+type_primitive *new_type_primitive (ident *name, ir_mode *mode);
+
+/* manipulate fields of type_primitive */
+char  *get_primitive_name  (type_primitive *primitive);
+ident *get_primitive_ident (type_primitive *primitive);
+/*
+void   set_primitive_name  (type_primitive *primitive, char *name);
+void   set_primitive_ident (type_primitive *primitive, ident* ident);
+*/
+ir_mode *get_primitive_mode (type_primitive *primitive);
+void     set_primitive_mode (type_primitive *primitive, ir_mode *mode);
+
+
+
+
+/*******************************************************************/
+/**  To manage all different types the same                       **/
+/*******************************************************************/
+
+union type {
+  firm_kind kind;
+  type_class clss;
+  type_strct strct;
+  type_method method;
+  type_array array;
+  type_union uni;  /* union is keyword */
+  type_enumeration enumeration;
+  type_pointer pointer;
+  type_primitive primitive;
+};
+
+int is_type(void *thing);
+
+
+
+
+# endif /* _TYPE_H_ */
diff --git a/ir/tr/type_or_entity.h b/ir/tr/type_or_entity.h
new file mode 100644 (file)
index 0000000..96566e5
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+
+** All rights reserved.
+**
+** Author: Goetz Lindenmaier
+**
+*/
+
+/* A datatype to treat types and entities as the same. */
+
+# ifndef _TYPE_OR_ENTITY_H_
+# define _TYPE_OR_ENTITY_H_
+
+typedef union {
+  type *typ;
+  entity *ent;
+} type_or_ent;
+
+
+# endif /* _TYPE_OR_ENTITY_H_ */
diff --git a/ir/tr/typewalk.c b/ir/tr/typewalk.c
new file mode 100644 (file)
index 0000000..b8752dc
--- /dev/null
@@ -0,0 +1,167 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Author: Goetz Lindenmaier
+**
+** traverse the type information.  The walker walks the whole ir graph
+** to find the distinct type trees in the type graph forest.
+** - execute the pre function before recursion
+** - execute the post function after recursion
+*/
+
+#include "irgwalk.h"
+#include "irgraph.h"
+#include "irnode.h"
+#include "type_or_entity.h"
+
+typedef struct type_walk_env {
+  void *pre;
+  void *post;
+  void *env;
+} type_walk_env;
+
+
+void type_walk_2(type_or_ent *tore,
+             void (pre)(type_or_ent*, void*), void (post)(type_or_ent*, void*),
+           void *env)
+{
+  int i, visited = 0;
+
+  /* marked? */
+  switch (get_kind(tore)) {
+  case k_entity:
+    if (((entity *)tore)->visit >= type_visited) visited = 1; break;
+  case k_type_class:
+    if (((type_class *)tore)->visit >= type_visited) visited = 1; break;
+  case k_type_strct:
+    if (((type_strct *)tore)->visit >= type_visited) visited = 1; break;
+  case k_type_method:
+    if (((type_method *)tore)->visit >= type_visited) visited = 1; break;
+  case k_type_union:
+    if (((type_union *)tore)->visit >= type_visited) visited = 1; break;
+  case k_type_array:
+    if (((type_array *)tore)->visit >= type_visited) visited = 1; break;
+  case k_type_enumeration:
+    if (((type_enumeration *)tore)->visit >= type_visited) visited = 1; break;
+  case k_type_pointer:
+    if (((type_pointer *)tore)->visit >= type_visited) visited = 1;  break;
+  case k_type_primitive:
+    if (((type_primitive *)tore)->visit >= type_visited) visited = 1;  break;
+  default:
+    break;
+  }
+
+  if (!visited) { /* not marked. */
+
+    /* execute pre method */
+    if(pre)
+      pre(tore, env);
+
+    /* iterate */
+    switch (get_kind(tore)) {
+    case k_entity:
+      {
+       entity *ent = (entity *)tore;
+       ent->visit = type_visited;
+       type_walk_2((type_or_ent *)get_entity_owner(ent), pre, post, env);
+       type_walk_2((type_or_ent *)get_entity_type(ent), pre, post, env);
+      }
+      break;
+    case k_type_class:
+      ((type_class *)tore)->visit = type_visited;
+      /* !!!!! */
+      break;
+    case k_type_strct:
+      ((type_strct *)tore)->visit = type_visited;
+      /* !!!!! */
+      break;
+    case k_type_method:
+      {
+       type_method *meth  = (type_method *)tore;
+       meth->visit = type_visited;
+       for (i = 0; i < get_method_arity(meth); i++)
+         type_walk_2((type_or_ent *)get_method_param_type(meth, i), pre, post, env);
+       for (i = 0; i < get_method_n_res(meth); i++)
+         type_walk_2((type_or_ent *)get_method_res_type(meth, i), pre, post, env);
+      }
+      break;
+    case k_type_union:
+      ((type_union *)tore)->visit = type_visited;
+      break;
+    case k_type_array:
+      ((type_array *)tore)->visit = type_visited;
+      type_walk_2((type_or_ent *)get_array_element_type((type_array *)tore),
+                 pre, post, env);
+      break;
+    case k_type_enumeration:
+      ((type_enumeration *)tore)->visit = type_visited;
+      /* a leave */
+      break;
+    case k_type_pointer:
+      ((type_pointer *)tore)->visit = type_visited;
+      type_walk_2((type_or_ent *)get_pointer_points_to_type((type_pointer *)tore),
+                 pre, post, env);
+      break;
+    case k_type_primitive:
+      ((type_primitive *)tore)->visit = type_visited;
+      /* a leave. */
+      break;
+    default:
+      break;
+    }
+
+    /* execute post method */
+    if(post)
+      post(tore, env);
+  }
+
+  return;
+}
+
+void start_type_walk(ir_node *node, void *env) {
+  void *pre  = ((type_walk_env *)env)->pre;
+  void *post = ((type_walk_env *)env)->post;
+  void *envi  = ((type_walk_env *)env)->env;
+
+  assert(node);
+
+    switch (get_irn_opcode(node)) {  /* node label */
+    case iro_SymConst:
+      if (   (get_SymConst_kind(node) == type_tag)
+         || (get_SymConst_kind(node) == size))
+       type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi);
+      break;
+    case iro_Sel:
+      type_walk_2((type_or_ent *)get_Sel_entity(node), pre, post, envi);
+      break;
+    case iro_Call:
+      type_walk_2((type_or_ent *)get_Call_type(node), pre, post, envi);
+      break;
+    case iro_Alloc:
+      type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi);
+    case iro_Free:
+      type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi);
+      break;
+  assert(node);
+    default:
+      break;
+    }
+}
+
+void type_walk(ir_graph *irg,
+             void (pre)(type_or_ent*, void*), void (post)(type_or_ent*, void*),
+             void *env)
+{
+  /* this is needed to pass the parameters to the walker that actually
+     walks the type information */
+  type_walk_env* type_env;
+  type_env = (type_walk_env *) malloc (sizeof(type_walk_env));
+  type_env->pre = pre;
+  type_env->post = post;
+  type_env->env = env;
+
+  ++type_visited;
+  irg_walk(irg->end, start_type_walk, NULL, type_env);
+
+  return;
+}
diff --git a/ir/tr/typewalk.h b/ir/tr/typewalk.h
new file mode 100644 (file)
index 0000000..8086598
--- /dev/null
@@ -0,0 +1,22 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+
+** All rights reserved.
+**
+** Author: Goetz Lindenmaier
+**
+** traverse the type information.  The walker walks the whole ir graph
+** to find the distinct type trees in the type graph forest.
+** - execute the pre function before recursion
+** - execute the post function after recursion
+*/
+
+
+/* walk over all type information reachable from the ir graph. */
+
+
+
+# include "type_or_entity.h"
+
+void type_walk(ir_graph *irg,
+             void (pre)(type_or_ent*, void*), void (post)(type_or_ent*, void*),
+              void *env);
diff --git a/ir/tv/Makefile b/ir/tv/Makefile
new file mode 100644 (file)
index 0000000..ce3ad51
--- /dev/null
@@ -0,0 +1,61 @@
+# Hey, emacs, this is a -*- makefile -*-
+#
+# Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+# All rights reserved.
+# Author: Goetz Lindenmaier
+#
+# Makefile for tv -- constant table and machine arithmetic
+CXX         = gcc
+CFLAGS      = -pipe -Wall # -ansi -pedantic
+CXXFLAGS    = # -g
+COPTFLAGS   = -O3
+LDFLAGS     =
+DEPENDFLAGS = -M
+LIBPATH     =
+LIBS        =
+X_LIBS      =
+INCLUDES    = -I../adt -I../common -I../debug -I../ident -I../include \
+             -I../ir -I../tr -I../tv
+X_INCLUDES  =
+
+SHELL       = /bin/sh
+MAKE        = /usr/bin/make
+
+MEMBERS         = tv.m label.m
+
+CFILES = $(MEMBERS:.m=.c)
+
+HFILES = $(MEMBERS:.m=.h)
+HFILES += ieee754.h
+
+HFILES += common.h debug.h entity.h gmp.h ident.h irmode.h obst.h \
+         pset.h tune.h type.h xprintf.h xp_help.h
+
+OFILES = $(MEMBERS:%.m=../objects/%.o)
+
+DFILES = $(MEMBERS:.m=.d)
+
+TARGET = all
+
+.PHONY: default all clean realclean install depend
+.SUFFIXES: .d .h .c .o
+.DEFAULT: $(TARGET)
+.SILENT: $(DFILES) clean  # hides output
+
+%.d:    %.c
+       $(SHELL) -ec '$(CXX) $(DEPENDFLAGS) $(INCLUDES) $(X_INCLUDES) $< | sed '\''s/$*\\.o[ :]*/& $@/g'\'' > $@'
+
+
+../objects/%.o:    %.c
+       $(CXX) $(CFLAGS) $(CXXFLAGS) $(COPTFLAGS) $(INCLUDES) $(X_INCLUDES) -c $< -o $@
+
+
+$(TARGET):      $(DFILES) $(OFILES)
+
+clean:
+       rm -f $(OFILES) $(DFILES)
+
+realclean:     clean
+       rm -f $(TARGET) *.flc TAGS
+
+-include $(DFILES)
diff --git a/ir/tv/ieee754.h b/ir/tv/ieee754.h
new file mode 100644 (file)
index 0000000..b61dc41
--- /dev/null
@@ -0,0 +1,121 @@
+/* IEEE754 fp format.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+/* This file was derived from the GNU C Library's ieee754.h which
+   carried the following copyright notice:
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* @@@ This is completely non-portable!  ISO/IEC DIS 9899, section
+   3.5.2.1: An implementation may allocate any addressable storage
+   unit large enough to hold a bit-field.  If enough space remains, a
+   bit-field that immediately follows another bit-field in a structure
+   shall be packed into adjacent bits of the same unit.  If
+   insufficient space remains, whether a bit-field that does not fit
+   is put into the next unit or overlaps adjacent units is
+   implementation-defined.  The order of allocation of bit-fields
+   within a unit (high-order to low-order or low-order to high-order)
+   is implementation-defined.  */
+
+#ifndef _IEEE754_H
+#define _IEEE754_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+union ieee754_double
+  {
+    double d;
+
+    /* This is the IEEE 754 double-precision format.  */
+    struct
+      {
+#ifdef WORDS_BIGENDIAN
+       unsigned int negative:1;
+       unsigned int exponent:11;
+       unsigned int mantissa0:20;
+       unsigned int mantissa1:32;
+#else
+       unsigned int mantissa1:32;
+       unsigned int mantissa0:20;
+       unsigned int exponent:11;
+       unsigned int negative:1;
+#endif
+      } ieee;
+    struct
+      {
+#ifdef WORDS_BIGENDIAN
+       unsigned int negative:1;
+       unsigned int exponent:11;
+       unsigned int quiet_nan:1;
+       unsigned int mantissa0:19;
+       unsigned int mantissa1:32;
+#else
+       unsigned int mantissa1:32;
+       unsigned int mantissa0:19;
+       unsigned int quiet_nan:1;
+       unsigned int exponent:11;
+       unsigned int negative:1;
+#endif
+      } ieee_nan;
+  };
+
+/* bias added to exponent of ieee754_double */
+#define _IEEE754_DOUBLE_BIAS 0x3ff
+
+
+union ieee754_float
+  {
+    float f;
+
+    /* This is the ieee754 single-precision format.  */
+    struct
+      {
+#ifdef WORDS_BIGENDIAN
+       unsigned int negative:1;
+       unsigned int exponent:8;
+       unsigned int mantissa:23;
+#else
+       unsigned int mantissa:23;
+       unsigned int exponent:8;
+       unsigned int negative:1;
+#endif
+      } ieee;
+    /* This is for extracting information about NaNs.  */
+    struct
+      {
+#ifdef WORDS_BIGENDIAN
+       unsigned int negative:1;
+       unsigned int exponent:8;
+       unsigned int quiet_nan:1;
+       unsigned int mantissa:22;
+#else
+       unsigned int mantissa:22;
+       unsigned int quiet_nan:1;
+       unsigned int exponent:8;
+       unsigned int negative:1;
+#endif
+      } ieee_nan;
+  };
+
+/* bias added to exponent of ieee_float */
+#define _IEEE754_FLOAT_BIAS 0x7f
+
+#endif /* _IEEE754_H */
diff --git a/ir/tv/label.c b/ir/tv/label.c
new file mode 100644 (file)
index 0000000..748c10e
--- /dev/null
@@ -0,0 +1,10 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+# include "label.h"
+
+label last_label;
diff --git a/ir/tv/label.h b/ir/tv/label.h
new file mode 100644 (file)
index 0000000..6d2efb2
--- /dev/null
@@ -0,0 +1,10 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Martin Trapp, Christian Schaefer
+**
+*/
+
+typedef unsigned long label;
+extern label last_label;
+#define new_label() (++last_label)
diff --git a/ir/tv/tv.c b/ir/tv/tv.c
new file mode 100644 (file)
index 0000000..25e79e7
--- /dev/null
@@ -0,0 +1,1655 @@
+/* TV --- Target Values, aka Constant Table.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+/* This implementation assumes:
+   * target characters/strings can be represented as type `char'/`char *',
+   * host's type `long'/`unsigned long' can hold values of mode `l'/`L',
+   * both host and target have two's complement integral arithmetic,
+     host's C operators `/' and `%' match target's div and mod.
+     target_max_<mode> == (1<<k)-1 for some k>0
+     target_min_<mode> == -target_max_<mode>-1
+     target_max_<Mode> == target_max_<mode>-target_min_<mode>
+   * both host and target have IEEE-754 floating-point arithmetic.  */
+
+/* !!! float and double divides MUST NOT SIGNAL !!! */
+/* @@@ query the floating-point expception status flags */
+
+/* @@@ ToDo: tarval_convert_to is not fully implemented! */
+/* @@@ Problem: All Values are stored twice, once as Univ_*s and a 2nd
+   time in their real target mode. :-( */
+/* @@@ Perhaps use a set instead of a pset: new tarvals allocated on
+   stack, copied into set by tarval_identify() if really new.  If
+   tarval_identify() discards often enough, the extra copy for kept
+   values is cheaper than the extra obstack_alloc()/free() for
+   discarded ones.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "pset.h"
+#define TOBSTACK_ID "tv"
+#include "obst.h"
+#include "ieee754.h"
+#include "tune.h"
+#include "ident.h"
+#include "tv.h"
+
+static struct obstack tv_obst; /* obstack for all the target values */
+static pset *tarvals;          /* pset containing pointers to _all_ tarvals */
+
+/* currently building an object with tarval_start() & friends ? */
+#define BUILDING obstack_object_size (&tv_obst)
+
+/* special tarvals: */
+tarval *tarval_bad;
+tarval *tarval_b_false;
+tarval *tarval_b_true;
+tarval *tarval_d_NaN;
+tarval *tarval_d_Inf;
+tarval *tarval_p_void;
+tarval *tarval_mode_null[irm_max];
+
+# if 0
+/* @@@ depends on order of ir_mode */
+static tarval_chil min_chil[8] = {
+  TARGET_SIMIN (c), 0,
+  TARGET_SIMIN (h), 0,
+  TARGET_SIMIN (i), 0,
+  TARGET_SIMIN (l), 0
+};
+static tarval_chil max_chil[8] = {
+  TARGET_SIMAX (c), TARGET_UIMAX (C),
+  TARGET_SIMAX (h), TARGET_UIMAX (H),
+  TARGET_SIMAX (i), TARGET_UIMAX (I),
+  TARGET_SIMAX (l), TARGET_UIMAX (L)
+};
+# endif
+
+/* return a mode-specific value */
+
+tarval_f
+tv_val_f (tarval *tv)
+{
+  return tv->u.f;
+}
+
+tarval_d
+tv_val_d (tarval *tv)
+{
+  return tv->u.d;
+}
+
+tarval_chil
+tv_val_chil (tarval *tv)
+{
+  return tv->u.chil;
+}
+
+tarval_CHIL
+tv_val_CHIL (tarval *tv)
+{
+  return tv->u.CHIL;
+}
+
+tarval_Z
+tv_val_Z (tarval *tv)
+{
+  return tv->u.Z;
+}
+
+tarval_p
+tv_val_p (tarval *tv)
+{
+  return tv->u.p;
+}
+
+bool
+tv_val_b (tarval *tv)
+{
+  return tv->u.b;
+}
+
+tarval_B
+tv_val_B (tarval *tv)
+{
+  return tv->u.B;
+}
+
+tarval_s
+tv_val_s (tarval *tv)
+{
+  return tv->u.s;
+}
+
+
+/* Overflows `chil' signed integral `mode'?  */
+static inline bool
+chil_overflow (tarval_chil chil, ir_mode *mode)
+{
+  assert (is_chilCHIL(mode->code));
+  return (mode->min && mode->max  /* only valid after firm initialization */
+         && (chil < tv_val_chil (mode->min) || tv_val_chil (mode->max) < chil));
+}
+
+
+/* Overflows `CHIL' unsigned integral `mode'?  */
+static inline bool
+CHIL_overflow (tarval_CHIL CHIL, ir_mode *mode)
+{
+  assert (is_chilCHIL(mode->code));
+  return (mode->max   /* only valid after firm initialization */
+         && tv_val_CHIL (mode->max) < CHIL);
+}
+
+
+#ifndef NDEBUG
+void
+_tarval_vrfy (const tarval *val)
+{
+  assert (val);
+  switch (val->mode->code) {
+    /* floating */
+  case irm_f:
+  case irm_d:
+    break;
+    /* integral */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    assert (!CHIL_overflow (val->u.CHIL, val->mode)); break;
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    assert (!chil_overflow (val->u.chil, val->mode)); break;
+  case irm_Z:
+    break;
+    /* strange */
+  case irm_p:
+    if (val->u.p.ent)
+      assert (val->u.p.ent->kind == k_entity);
+    assert (   val->u.p.xname || val->u.p.ent
+           || !tarval_p_void || (val == tarval_p_void));
+    break;
+  case irm_s:
+  case irm_S:
+    assert (val->u.s.p); break;
+  case irm_B:
+    assert (val->u.B.p); break;
+  case irm_b:
+    assert ((unsigned)val->u.b <= 1); break;
+  default:
+    assert (val->mode == mode_T);
+  }
+}
+#endif
+
+
+#ifdef STATS
+
+void
+tarval_stats (void)
+{
+  pset_stats (tarvals);
+}
+
+#endif
+
+
+/* Return the canonical tarval * for tv.
+   May destroy everything allocated on tv_obst after tv!  */
+static tarval *
+tarval_identify (tarval *tv)
+{
+  tarval *o;
+
+  o = pset_insert (tarvals, tv, tarval_hash (tv));
+
+  if (o != tv) {
+    obstack_free (&tv_obst, (void *)tv);
+  }
+
+  TARVAL_VRFY (o);
+  return o;
+}
+
+
+/* Return 0 iff a equals b.  Bitwise identical NaNs compare equal.  */
+static int
+tarval_cmp (const void *p, const void *q)
+{
+  const tarval *a = p;
+  const tarval *b = q;
+
+  TARVAL_VRFY (a);
+  TARVAL_VRFY (b);
+
+  if (a == b) return 0;
+  if (a->mode - b->mode) return a->mode - b->mode;
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f:
+    return memcmp (&a->u.f, &b->u.f, sizeof (a->u.f));
+  case irm_d:
+    return memcmp (&a->u.d, &b->u.d, sizeof (a->u.d));
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    if (sizeof (int) == sizeof (tarval_CHIL)) {
+      return a->u.CHIL - b->u.CHIL;
+    }
+    return a->u.CHIL != b->u.CHIL;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    if (sizeof (int) == sizeof (tarval_chil)) {
+      return a->u.chil - b->u.chil;
+    }
+    return a->u.chil != b->u.chil;
+  case irm_Z:
+    return mpz_cmp (&a->u.Z, &b->u.Z);
+    /* strange */
+  case irm_p:
+    if (a->u.p.ent || b->u.p.ent)
+      return (char *)a->u.p.ent - (char *)b->u.p.ent;
+    if (a->u.p.xname && b->u.p.xname)
+      return strcmp (a->u.p.xname, b->u.p.xname);
+    return a->u.p.xname - b->u.p.xname;
+  case irm_b:
+    return a->u.b - b->u.b;
+  case irm_B:
+    return (  a->u.B.n - b->u.B.n
+           ? memcmp (a->u.B.p, b->u.B.p, a->u.B.n)
+           : a->u.B.n - b->u.B.n);
+  case irm_s: case irm_S:
+    return (  a->u.s.n == b->u.s.n
+           ? memcmp (a->u.s.p, b->u.s.p, a->u.s.n)
+           : a->u.s.n - b->u.s.n);
+  default: assert (0);
+  }
+}
+
+
+unsigned
+tarval_hash (tarval *tv)
+{
+  unsigned h;
+
+  h = tv->mode->code * 0x421u;
+  switch (tv->mode->code) {
+  case irm_T:
+    h = 0x94b527ce; break;
+  case irm_f:
+    /* quick & dirty */
+    { union { float f; unsigned u; } u;
+      assert (sizeof (float) <= sizeof (unsigned));
+      u.u = 0; u.f = tv->u.f;
+      h ^= u.u;
+      break;
+    }
+  case irm_d:
+    /* quick & dirty */
+    { union { double d; unsigned u[2]; } u;
+      assert (sizeof (double) <= 2*sizeof (unsigned));
+      u.u[0] = u.u[1] = 0; u.d = tv->u.d;
+      h ^= u.u[0] ^ u.u[1];
+      break;
+    }
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    h ^= tv->u.CHIL; break;
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    h ^= tv->u.chil; break;
+  case irm_Z:
+    h ^= mpz_get_ui (&tv->u.Z); break;
+  case irm_p:
+    if (tv->u.p.ent) {
+      /* @@@ lower bits not random, watch for collisions; perhaps
+        replace by tv->u.p.ent - (entity *)0 */
+      h ^= ((char *)tv->u.p.ent - (char *)0) / 64;
+    } else if (tv->u.p.xname) {
+      /* Of course, strlen() in a hash function is a mistake, but this
+         case should be really rare.  */
+      h ^= ID_HASH (tv->u.p.xname, strlen (tv->u.p.xname));
+    } else {                   /* void */
+      h^= 0x2b592b88;
+    }
+    break;
+  case irm_b:
+    h ^= tv->u.b; break;
+  case irm_B:
+    h ^= tv->u.B.n; break; /* @@@ not really good */
+  case irm_s:
+    h ^= tv->u.s.p[0]<<12 ^ tv->u.s.p[tv->u.s.n]<<4 ^ tv->u.s.n; break;
+  case irm_S:
+    h ^= tv->u.s.p[0]<<4 ^ tv->u.s.p[tv->u.s.n]<<12 ^ tv->u.s.n; break;
+  default:
+    assert(0);
+  }
+  return h;
+}
+
+
+\f
+/******************** Initialization ****************************************/
+
+void
+tarval_init_1 (void)
+{
+  obstack_init (&tv_obst);
+  obstack_alignment_mask (&tv_obst) = ALIGNOF (tarval) - 1;
+  assert (IS_POW2 (ALIGNOF (tarval)));
+
+  /* initialize the target value table */
+  tarvals = new_pset (tarval_cmp, TUNE_NCONSTANTS);
+}
+
+void
+tarval_init_2 (void)
+{
+  tarval *tv;
+  union ieee754_double x;
+
+  /* assumed by tarval_hash(): */
+  assert (sizeof (float) * CHAR_BIT == 32);
+  assert (sizeof (double) * CHAR_BIT == 64);
+
+# if 0
+  /* assumed by tarval_chil & friends: */
+  assert (   (irm_C == irm_c+1) && (irm_h == irm_C+1)
+         && (irm_H == irm_h+1) && (irm_i == irm_H+1)
+         && (irm_I == irm_i+1) && (irm_l == irm_I+1)
+         && (irm_L == irm_l+1));
+
+  /* assumed everywhere: */
+  for (i = 0;  i <= irm_L-irm_c;  i += 2) {
+    assert (   IS_POW2 (max_chil[i+1]+1)
+           && (min_chil[i] == -max_chil[i]-1)
+           && ((tarval_CHIL)max_chil[i+1] == (tarval_CHIL)max_chil[i]-min_chil[i]));
+  }
+# endif
+
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = mode_T;
+  tv->lab = 0;
+  tarval_bad = tarval_identify (tv);
+
+  tarval_b_false = tarval_from_long (mode_b, 0);
+  tarval_b_true = tarval_from_long (mode_b, 1);
+
+  /* IsInf <-> exponent == 0x7ff && ! (bits | fraction_low) */
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = mode_d;
+  tv->lab = 0;
+  x.ieee.negative = 0;
+  x.ieee.exponent = 0x7ff;
+  x.ieee.mantissa0 = 0;
+  x.ieee.mantissa1 = 0;
+  tv->u.d = x.d;
+  tarval_d_Inf = tarval_identify (tv);
+
+  /* IsNaN <-> exponent==0x7ff  && (qnan_bit | bits | fraction_low) */
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = mode_d;
+  tv->lab = 0;
+  x.ieee_nan.negative = 0;
+  x.ieee_nan.exponent = 0x7ff;
+  x.ieee_nan.quiet_nan = 1;    /* @@@ quiet or signalling? */
+  x.ieee_nan.mantissa0 = 42;
+  x.ieee_nan.mantissa1 = 0;
+  assert(x.d != x.d /* x.d is NaN */);
+  tv->u.d = x.d;
+  tarval_d_NaN = tarval_identify (tv);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = mode_p;
+  tv->lab = 0;
+  tv->u.p.xname = NULL;
+  tv->u.p.ent = NULL;
+  tv->u.p.tv = NULL;
+  tarval_p_void = tarval_identify (tv);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+
+  tarval_mode_null [irm_f] = tarval_from_long (mode_f, 0);
+  tarval_mode_null [irm_d] = tarval_from_long (mode_d, 0);
+  tarval_mode_null [irm_c] = tarval_from_long (mode_c, 0);
+  tarval_mode_null [irm_C] = tarval_from_long (mode_C, 0);
+  tarval_mode_null [irm_h] = tarval_from_long (mode_h, 0);
+  tarval_mode_null [irm_H] = tarval_from_long (mode_H, 0);
+  tarval_mode_null [irm_i] = tarval_from_long (mode_i, 0);
+  tarval_mode_null [irm_I] = tarval_from_long (mode_I, 0);
+  tarval_mode_null [irm_l] = tarval_from_long (mode_l, 0);
+  tarval_mode_null [irm_L] = tarval_from_long (mode_L, 0);
+  tarval_mode_null [irm_b] = tarval_b_false;
+  tarval_mode_null [irm_p] = tarval_p_void;
+}
+
+
+\f
+/************************* Constructors for tarvals *************************/
+
+/* copy from src to dst len chars omitting '_'. */
+static char *
+stripcpy (char *dst, const char *src, size_t len)
+{
+  char *d = dst;
+
+  while (len--) {
+    if (*src == '_') src++;
+    else *d++ = *src++;
+  }
+  *d = 0;                      /* make it 0-terminated. */
+
+  return dst;
+}
+
+
+tarval *
+tarval_Z_from_str (const char *s, size_t len, int base)
+{
+  tarval *tv;
+  char *buf;
+
+  assert (!BUILDING);
+
+  buf = alloca (len+1);
+  stripcpy (buf, s, len);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = mode_Z;
+  tv->lab = 0;
+  if (mpz_init_set_str (&tv->u.Z, buf, base)) assert (0);
+
+  return tarval_identify (tv);
+}
+
+
+tarval *
+tarval_B_from_str (const char *s, size_t len)
+{
+  tarval *tv;
+  size_t n;                    /* size of B */
+  const char *r;               /* read ptr */
+  unsigned x;                  /* bit store */
+  int b;                       /* bits in x */
+  int shift;                   /* base shift */
+
+  assert (!BUILDING);
+  assert (len >= 3);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = mode_B;
+  tv->lab = 0;
+
+  assert (s[0] == '0');
+  switch (s[1]) {
+  case 'o':
+  case 'O': shift = 3; break;
+  case 'x':
+  case 'X': shift = 4; break;
+  default: assert(0);
+  }
+
+  r = s+len;                   /* set r past input */
+  s += 2;                      /* skip header */
+  x = 0; b = 0; n = 0;
+  while (--r >= s) {
+    int d;                     /* digit */
+
+    if (*r == '_') continue;   /* skip _ styropor */
+    if (('0' <= *r) && (*r <= '9')) {
+      d = *r - '0';
+    } else if (('a' <= *r) && (*r <= 'f')) {
+      d = *r - 'a' + 10;
+    } else { assert (('A' <= *r) && (*r <= 'F'));
+      d = *r - 'A' + 10;
+    }
+
+    x |= d << b;               /* insert d into x above the b present bits */
+    b += shift;                        /* x now contains shift more bits */
+
+    if (b >= 8) {              /* we've accumulated at least a byte */
+      char c = x & 0xFF;       /* extract the lower 8 bits from x */
+      obstack_grow (&tv_obst, &c, 1); /* and stuff them into B */
+      x >>= 8;                 /* remove the lower 8 bits from x */
+      b -= 8;                  /* x now contains 8 bits fewer */
+      ++n;                     /* B grew a byte */
+    }
+  }
+
+  if (b >= 0) {                        /* flush the rest of the bits */
+    char c = x;                        /* extract them */
+    obstack_grow (&tv_obst, &c, 1); /* and stuff them into B */
+    ++n;                       /* B grew a byte */
+  }
+
+  { unsigned char *p = obstack_finish (&tv_obst);
+    unsigned char *q = p + n;
+
+    tv->u.B.p = p;
+    tv->u.B.n = n;
+    /* reverse p in place */
+    while (p < q) { char c = *p; *p++ = *q; *q-- = c; }
+  }
+
+  return tarval_identify (tv);
+}
+
+
+tarval *
+tarval_d_from_str (const char *s, size_t len)
+{
+  tarval *tv;
+  char *buf;
+  char *eptr;
+
+  assert (!BUILDING);
+
+  buf = alloca (len+1);
+  stripcpy (buf, s, len);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = mode_d;
+  tv->lab = 0;
+  tv->u.d = strtod (buf, &eptr);
+  assert (eptr == buf+strlen(buf));
+
+  return tarval_identify (tv);
+}
+
+
+tarval *
+tarval_s_from_str (const char *s, size_t len)
+{
+  tarval *tv;
+
+  assert (!BUILDING);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = mode_s;
+  tv->lab = 0;
+  tv->u.s.n = len;
+  tv->u.s.p = obstack_copy (&tv_obst, s, len);
+
+  return tarval_identify (tv);
+}
+
+tarval *
+tarval_S_from_str (const char *s, size_t len)
+{
+  tarval *tv;
+
+  assert (!BUILDING);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = mode_S;
+  tv->lab = 0;
+  tv->u.s.n = len;
+  tv->u.s.p = obstack_copy (&tv_obst, s, len);
+
+  return tarval_identify (tv);
+}
+
+
+/* Create a tarval with mode `m' and value `i' casted to the type that
+   represents such tarvals on host.  The resulting value must be legal
+   for mode `m'.  */
+tarval *
+tarval_from_long (ir_mode *m, long val)
+{
+  tarval *tv;
+
+  assert (!BUILDING);
+
+  if (m == mode_T) return tarval_bad;
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = m;
+  tv->lab = 0;
+  switch (m->code) {
+    /* floating */
+  case irm_f:
+    tv->u.f = val; break;
+  case irm_d:
+    tv->u.d = val; break;
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = val; break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = val; break;
+  case irm_Z:
+    mpz_init_set_si (&tv->u.Z, val);
+    break;
+    /* strange */
+  case irm_p:
+    assert(!val);
+    obstack_free (&tv_obst, tv);
+    return tarval_p_void;
+  case irm_b:
+    tv->u.b = !!val;           /* u.b must be 0 or 1 */
+    break;
+  default:
+    assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+tarval *
+tarval_p_from_str (const char *xname)
+{
+  tarval *tv;
+
+  assert (!BUILDING);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = mode_p;
+  tv->lab = 0;
+  tv->u.p.xname = obstack_copy0 (&tv_obst, xname, strlen (xname));
+  tv->u.p.ent = NULL;
+  tv->u.p.tv = NULL;
+  return tarval_identify (tv);
+}
+
+
+tarval *
+tarval_p_from_entity (entity *ent)
+{
+  tarval *tv;
+
+  assert (!BUILDING);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = mode_p;
+  tv->lab = 0;
+  tv->u.p.xname = NULL;
+  tv->u.p.ent = ent;
+  tv->u.p.tv = NULL;
+  return tarval_identify (tv);
+}
+
+
+/* Routines for building a tarval step by step follow.
+   Legal calling sequences:
+     tarval_start()
+     No contructors except tarval_append() and tarval_append1 ()
+     tarval_finish_as() or tarval_cancel() */
+
+/* Begin building a tarval.  */
+void
+tarval_start (void)
+{
+  assert (!BUILDING);
+  obstack_blank (&tv_obst, sizeof (tarval));
+}
+
+
+/* Append `n' chars from `p' to the tarval currently under construction.  */
+void
+tarval_append (const char *p, size_t n)
+{
+  assert (BUILDING);
+  obstack_grow (&tv_obst, p, n);
+}
+
+
+/* Append `ch' to the tarval currently under construction.  */
+void
+tarval_append1 (char ch)
+{
+  assert (BUILDING);
+  obstack_1grow (&tv_obst, ch);
+}
+
+
+/* Finish the tarval currently under construction and give id mode `m'.
+   `m' must be irm_C, irm_B, irm_s or irm_S.
+   Return NULL if the value does not make sense for this mode, this
+   can only happen in mode C.  */
+tarval *
+tarval_finish_as (ir_mode *m)
+{
+  int size = obstack_object_size (&tv_obst) - sizeof (tarval);
+  tarval *tv;
+  unsigned char *p;
+  char ch = 0;                 /* initialized to shut up gcc */
+
+  assert (BUILDING && (size >= 0));
+  if (m == mode_C) {
+    if (size != 1) return tarval_cancel();
+    p = (unsigned char *)obstack_base (&tv_obst) + sizeof (tarval);
+    ch = *p;
+    obstack_blank (&tv_obst, -size);
+  }
+  tv = obstack_finish (&tv_obst);
+  p = (unsigned char *)tv + sizeof (tarval);
+  tv->mode = m;
+  tv->lab = 0;
+
+  switch (m->code) {
+  case irm_C:
+    tv->u.CHIL = ch;
+    break;
+  case irm_B:
+    tv->u.B.n = size;
+    tv->u.B.p = p;
+    break;
+  case irm_s:
+  case irm_S:
+    tv->u.s.n = size;
+    tv->u.s.p = p;
+    break;
+  case irm_p:
+    tv->u.p.tv = NULL;
+    break;
+  default:
+    assert (0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Cancel tarval building and return tarval_bad.  */
+tarval *
+tarval_cancel (void)
+{
+  assert (BUILDING);
+  obstack_free (&tv_obst, obstack_finish (&tv_obst));
+  return tarval_bad;
+}
+
+
+\f
+/********************* Arithmethic operations on tarvals ********************/
+
+/* Return `src' converted to mode `m' if representable, else NULL.
+   @@@ lots of conversions missing */
+tarval *
+tarval_convert_to (tarval *src, ir_mode *m)
+{
+  tarval *tv;
+
+  if (m == src->mode) return src;
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = m;
+  tv->lab = 0;
+
+  switch (src->mode->code) {
+
+  case irm_d:
+    if (m != mode_f) goto fail;
+    tv->u.f = src->u.d;
+    break;
+
+  case irm_Z:
+    switch (m->code) {
+
+    case irm_C: case irm_H: case irm_I: case irm_L:
+      if (mpz_cmp_si (&src->u.Z, 0) < 0) goto fail;
+      if (mpz_size (&src->u.Z) > 1) goto fail;
+      tv->u.CHIL = mpz_get_ui (&src->u.Z);
+      if (CHIL_overflow (tv->u.CHIL, m)) goto fail;
+      break;
+
+    case irm_c: case irm_h: case irm_i: case irm_l:
+      tv->u.chil = mpz_get_si (&src->u.Z);
+      if (chil_overflow (tv->u.chil, m)) goto fail;
+      break;
+
+    case irm_b:
+      tv ->u.b = !mpz_cmp_ui (&src->u.Z, 0);
+      break;
+
+    case irm_p:
+      if (mpz_cmp_ui (&src->u.Z, 0)) goto fail;
+      obstack_free (&tv_obst, tv);
+      return tarval_p_void;
+
+    default: goto fail;
+    }
+    break;
+
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    switch (m->code) {
+    case irm_c: case irm_h: case irm_i: case irm_l:
+      tv->u.chil = src->u.chil;
+      if (chil_overflow (tv->u.chil, m)) goto fail;
+      break;
+
+    case irm_C: case irm_H: case irm_I: case irm_L:
+      tv->u.CHIL = src->u.chil;
+      if (CHIL_overflow (tv->u.CHIL, m)) goto fail;
+      break;
+
+    case irm_Z:
+      mpz_init_set_si (&tv->u.Z, src->u.chil);
+      break;
+
+    case irm_b:
+      tv->u.b = !!src->u.chil;
+      break;
+
+    default: goto fail;
+    }
+
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    switch (m->code) {
+    case irm_c: case irm_h: case irm_i: case irm_l:
+      tv->u.chil = src->u.CHIL;
+      if (chil_overflow (tv->u.chil, m)) goto fail;
+      break;
+
+    case irm_C: case irm_H: case irm_I: case irm_L:
+      tv->u.CHIL = src->u.CHIL;
+      if (CHIL_overflow (tv->u.CHIL, m)) goto fail;
+      break;
+
+    case irm_Z:
+      mpz_init_set_ui (&tv->u.Z, src->u.CHIL);
+      break;
+
+    case irm_b:
+      tv->u.b = !!src->u.CHIL;
+      break;
+
+    default: goto fail;
+    }
+    break;
+
+  case irm_b:
+    switch (m->code) {
+    case irm_c: case irm_h: case irm_i: case irm_l:
+      tv->u.chil = src->u.b;
+      break;
+
+    case irm_C: case irm_H: case irm_I: case irm_L:
+      tv->u.CHIL = src->u.b;
+
+    default: goto fail;
+    }
+    break;
+
+  default:
+  fail:
+    obstack_free (&tv_obst, tv);
+    return NULL;
+  }
+
+  return tarval_identify (tv);
+}
+
+
+tarval *
+tarval_neg (tarval *a)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f: tv->u.f = -a->u.f; break;
+  case irm_d: tv->u.d = -a->u.d; break;
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = -a->u.CHIL & tv_val_CHIL (a->mode->max);
+    break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = -a->u.chil;
+    if (   chil_overflow (tv->u.chil, a->mode)
+       || ((tv->u.chil >= 0) == (a->u.chil >= 0))) {
+      obstack_free (&tv_obst, tv);
+      return NULL;
+    }
+    break;
+  case irm_Z:
+    mpz_init (&tv->u.Z);
+    mpz_neg (&tv->u.Z, &a->u.Z);
+    break;
+    /* strange */
+  case irm_b: tv->u.b = !a->u.b; break;
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Compare `a' with `b'.
+   Return one of irpn_Lt, irpn_Eq, irpn_Gt, irpn_Uo, or irpn_False if
+   result is unknown.  */
+ir_pncmp
+tarval_comp (tarval *a, tarval *b)
+{
+
+  TARVAL_VRFY (a);
+  TARVAL_VRFY (b);
+
+  assert (a->mode == b->mode);
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f: return (  a->u.f == b->u.f ? irpn_Eq
+                     : a->u.f > b->u.f ? irpn_Gt
+                     : a->u.f < b->u.f ? irpn_Lt
+                     : irpn_Uo);
+  case irm_d: return (  a->u.d == b->u.d ? irpn_Eq
+                     : a->u.d > b->u.d ? irpn_Gt
+                     : a->u.d < b->u.d ? irpn_Lt
+                     : irpn_Uo);
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    return (  a->u.CHIL == b->u.CHIL ? irpn_Eq
+           : a->u.CHIL > b->u.CHIL ? irpn_Gt
+           : irpn_Lt);
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    return (  a->u.chil == b->u.chil ? irpn_Eq
+           : a->u.chil > b->u.chil ? irpn_Gt
+           : irpn_Lt);
+  case irm_Z:
+    { int cmp = mpz_cmp (&a->u.Z, &b->u.Z);
+      return (  cmp == 0 ? irpn_Eq
+             : cmp > 0 ? irpn_Gt
+             : irpn_Lt);
+    }
+    /* strange */
+  case irm_b: return (  a->u.b == b->u.b ? irpn_Eq
+                     : a->u.b > b->u.b ? irpn_Gt
+                     : irpn_Lt);
+  /* The following assumes that pointers are unsigned, which is valid
+     for all sane CPUs (transputers are insane). */
+  case irm_p: return (  a == b ? irpn_Eq
+                     : a == tarval_p_void ? irpn_Lt
+                     : b == tarval_p_void ? irpn_Gt
+                     : irpn_False); /* unknown */
+  default: assert (0);
+  }
+}
+
+
+/* Return `a+b' if computable, else NULL.  Modes must be equal.  */
+tarval *
+tarval_add (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f: tv->u.f = a->u.f + b->u.f; break;        /* @@@ overflow etc */
+  case irm_d: tv->u.d = a->u.d + b->u.d; break; /* @@@ dto. */
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = (a->u.CHIL + b->u.CHIL) & tv_val_CHIL (a->mode->max);
+    break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = a->u.chil + b->u.chil;
+    if (   chil_overflow (tv->u.chil, a->mode)
+       || ((tv->u.chil > a->u.chil) ^ (b->u.chil > 0))) {
+      obstack_free (&tv_obst, tv);
+      return NULL;
+    }
+    break;
+  case irm_Z:
+    mpz_init (&tv->u.Z);
+    mpz_add (&tv->u.Z, &a->u.Z, &b->u.Z);
+    break;
+    /* strange */
+  case irm_b: tv->u.b = a->u.b | b->u.b; break;        /* u.b is in canonical form */
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a-b' if computable, else NULL.  Modes must be equal.  */
+tarval *
+tarval_sub (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f: tv->u.f = a->u.f - b->u.f; break;        /* @@@ overflow etc */
+  case irm_d: tv->u.d = a->u.d - b->u.d; break; /* @@@ dto. */
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = (a->u.CHIL - b->u.CHIL) & tv_val_CHIL (a->mode->max);
+    break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = a->u.chil - b->u.chil;
+    if (   chil_overflow (tv->u.chil, a->mode)
+       || ((tv->u.chil > a->u.chil) ^ (b->u.chil < 0))) {
+      obstack_free (&tv_obst, tv);
+      return NULL;
+    }
+    break;
+  case irm_Z:
+    mpz_init (&tv->u.Z);
+    mpz_sub (&tv->u.Z, &a->u.Z, &b->u.Z);
+    break;
+    /* strange */
+  case irm_b: tv->u.b = a->u.b & ~b->u.b; break; /* u.b is in canonical form */
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a*b' if computable, else NULL.  Modes must be equal.  */
+tarval *
+tarval_mul (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f: tv->u.f = a->u.f * b->u.f; break;        /* @@@ overflow etc */
+  case irm_d: tv->u.d = a->u.d * b->u.d; break; /* @@@ dto. */
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = (a->u.CHIL * b->u.CHIL) & tv_val_CHIL (a->mode->max);
+    break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = a->u.chil * b->u.chil;
+    if (   chil_overflow (tv->u.chil, a->mode)
+       || (b->u.chil && (tv->u.chil / b->u.chil != a->u.chil))) {
+      obstack_free (&tv_obst, tv);
+      return NULL;
+    }
+    break;
+  case irm_Z:
+    mpz_init (&tv->u.Z);
+    mpz_mul (&tv->u.Z, &a->u.Z, &b->u.Z);
+    break;
+    /* strange */
+  case irm_b: tv->u.b = a->u.b & b->u.b; break;        /* u.b is in canonical form */
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return floating-point `a/b' if computable, else NULL.
+   Modes must be equal, non-floating-point operands are converted to irm_d.  */
+tarval *
+tarval_quo (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f:
+    tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+    tv->mode = mode_f;
+    tv->lab = 0;
+    tv->u.f = a->u.f / b->u.f; /* @@@ overflow etc */
+    break;
+  case irm_d:
+    tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+    tv->mode = mode_d;
+    tv->lab = 0;
+    tv->u.d = a->u.d / b->u.d; /* @@@ overflow etc */
+    break;
+  default:
+    a = tarval_convert_to (a, mode_d);
+    b = tarval_convert_to (b, mode_d);
+    return a && b ? tarval_quo (a, b) : NULL;
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a/b' if computable, else NULL.  Modes must be equal.  */
+tarval *
+tarval_div (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f: tv->u.f = floor (a->u.f / b->u.f); break; /* @@@ overflow etc */
+  case irm_d: tv->u.d = floor (a->u.d / b->u.d); break; /* @@@ dto. */
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    if (!b->u.CHIL) goto fail;
+    tv->u.CHIL = a->u.CHIL / b->u.CHIL;
+    break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    if (   !b->u.chil
+       || ((b->u.chil == -1) && (a->u.chil == tv_val_chil (a->mode->max) ))) {
+    fail:
+      obstack_free (&tv_obst, tv);
+      return NULL;
+    }
+    tv->u.chil = a->u.chil / b->u.chil;
+    break;
+  case irm_Z:
+    if (!mpz_cmp_ui (&b->u.Z, 0)) goto fail;
+    mpz_init (&tv->u.Z);
+    mpz_div (&tv->u.Z, &a->u.Z, &b->u.Z);
+    break;
+    /* strange */
+  case irm_b: tv->u.b = a->u.b ^ b->u.b; break;        /* u.b is in canonical form */
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a%b' if computable, else NULL.  Modes must be equal.  */
+tarval *
+tarval_mod (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* floating */
+  case irm_f: tv->u.f = fmod (a->u.f, b->u.f); break; /* @@@ overflow etc */
+  case irm_d: tv->u.d = fmod (a->u.d, b->u.d); break; /* @@@ dto */
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    if (!b->u.CHIL) goto fail;
+    tv->u.CHIL = a->u.CHIL % b->u.CHIL;
+    break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    if (!b->u.chil) {
+    fail:
+      obstack_free (&tv_obst, tv);
+      return NULL;
+    }
+    tv->u.chil = a->u.chil % b->u.chil;
+    break;
+  case irm_Z:
+    if (!mpz_cmp_ui (&b->u.Z, 0)) goto fail;
+    mpz_init (&tv->u.Z);
+    mpz_mod (&tv->u.Z, &a->u.Z, &b->u.Z);
+    break;
+    /* strange */
+  case irm_b: tv->u.b = a->u.b ^ b->u.b; break;        /* u.b is in canonical form */
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a&b'.  Modes must be equal.  */
+tarval *
+tarval_and (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = a->u.CHIL & b->u.CHIL; break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = a->u.chil & b->u.chil; break;
+  case irm_Z:
+    mpz_init (&tv->u.Z);
+    mpz_and (&tv->u.Z, &a->u.Z, &b->u.Z);
+    break;
+    /* strange */
+  case irm_b: tv->u.b = a->u.b & b->u.b; break;        /* u.b is in canonical form */
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a|b'.  Modes must be equal.  */
+tarval *
+tarval_or (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = a->u.CHIL | b->u.CHIL; break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = a->u.chil | b->u.chil; break;
+  case irm_Z:
+    mpz_init (&tv->u.Z);
+    mpz_ior (&tv->u.Z, &a->u.Z, &b->u.Z);
+    break;
+    /* strange */
+  case irm_b: tv->u.b = a->u.b | b->u.b; break;        /* u.b is in canonical form */
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a^b'.  Modes must be equal.  */
+tarval *
+tarval_eor (tarval *a, tarval *b)
+{
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+  assert (a->mode == b->mode);
+
+#if 1 /* see case irm_Z below */
+  if (a->mode == mode_Z) return NULL;
+#endif
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = a->u.CHIL ^ b->u.CHIL; break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = a->u.chil ^ b->u.chil; break;
+  case irm_Z:
+#if 0 /* gmp-1.3.2 declares but does not define mpz_xor() */
+    mpz_init (&tv->u.Z);
+    mpz_xor (&tv->u.Z, &a->u.Z, &b->u.Z);
+#endif
+    break;
+    /* strange */
+  case irm_b: tv->u.b = a->u.b ^ b->u.b; break;        /* u.b is in canonical form */
+  default: assert(0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a<<b' if computable, else NULL.  */
+tarval *
+tarval_shl (tarval *a, tarval *b)
+{
+  int b_is_huge;
+  long shift;
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+
+  shift = tarval_ord (b, &b_is_huge);
+  if (   b_is_huge
+      || (shift < 0)
+      || ((shift >= mode_l->size*target_bits) && (a->mode != mode_Z))) {
+    return NULL;
+  }
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = a->u.CHIL << shift;
+    break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = a->u.chil << shift;
+    break;
+  case irm_Z:
+    mpz_init (&tv->u.Z);
+    mpz_mul_2exp (&tv->u.Z, &a->u.Z, shift);
+    break;
+  default: assert (0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Return `a>>b' if computable, else NULL.  */
+tarval *
+tarval_shr (tarval *a, tarval *b)
+{
+  int b_is_huge;
+  long shift;
+  tarval *tv;
+
+  TARVAL_VRFY (a); TARVAL_VRFY (b);
+
+  shift = tarval_ord (b, &b_is_huge);
+  if (   b_is_huge
+      || (shift < 0)
+      || ((shift >= mode_l->size*target_bits) && (a->mode != mode_Z))) {
+    return NULL;
+  }
+
+  tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
+  tv->mode = a->mode;
+  tv->lab = 0;
+
+  switch (a->mode->code) {
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    tv->u.CHIL = a->u.CHIL >> shift;
+    break;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    tv->u.chil = a->u.chil >> shift;
+    break;
+  case irm_Z:
+    mpz_init (&tv->u.Z);
+    mpz_div_2exp (&tv->u.Z, &a->u.Z, shift);
+    break;
+  default: assert (0);
+  }
+
+  return tarval_identify (tv);
+}
+
+
+/* Classify `tv', which may be NULL.
+   Return 0 if `tv' is the additive neutral element, 1 if `tv' is the
+   multiplicative neutral element, and -1 if `tv' is the neutral
+   element of bitwise and.  */
+long
+tarval_classify (tarval *tv)
+{
+  if (!tv) return 2;
+
+  TARVAL_VRFY (tv);
+
+  switch (tv->mode->code) {
+    /* floating */
+  case irm_f: case irm_d:
+    return 2;
+    /* unsigned */
+  case irm_C:
+    return (long)((tv->u.CHIL+1) & tv_val_CHIL (mode_C->max)) - 1;
+  case irm_H:
+    return (long)((tv->u.CHIL+1) & tv_val_CHIL (mode_H->max)) - 1;
+  case irm_I:
+    return (long)((tv->u.CHIL+1) & tv_val_CHIL (mode_I->max)) - 1;
+  case irm_L:
+    return (long)((tv->u.CHIL+1) & tv_val_CHIL (mode_L->max)) - 1;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    return tv->u.chil;
+  case irm_Z:
+    if      (mpz_cmp_si (&tv->u.Z, 0)) return 0;
+    else if (mpz_cmp_si (&tv->u.Z, 1)) return 1;
+    else if (mpz_cmp_si (&tv->u.Z,-1)) return -1;
+    return 2;
+    /* strange */
+  case irm_b:
+    return tv->u.b;
+  default:
+    return 2;
+  }
+}
+
+
+bool
+tarval_s_fits (tarval *tv, long min, long max) {
+  return ((  mpz_cmp_si (&tv->u.Z, min) >= 0)
+         && mpz_cmp_si (&tv->u.Z, max) <= 0);
+}
+
+bool
+tarval_u_fits (tarval *tv, unsigned long max) {
+  return ((  mpz_sgn (&tv->u.Z) >= 0)
+         && mpz_cmp_si (&tv->u.Z, max) <= 0);
+}
+
+
+/* Convert `tv' into type `long', set `fail' if not representable.
+   If `fail' gets set for an unsigned `tv', the correct result can be
+   obtained by casting the result to `unsigned long'.  */
+long
+tarval_ord (tarval *tv, int *fail)
+{
+  TARVAL_VRFY (tv);
+
+  switch (tv->mode->code) {
+    /* unsigned */
+  case irm_C: case irm_H: case irm_I: case irm_L:
+    *fail = tv->u.CHIL > tv_val_CHIL (mode_l->max);
+    return tv->u.CHIL;
+    /* signed */
+  case irm_c: case irm_h: case irm_i: case irm_l:
+    *fail = 0;
+    return tv->u.chil;
+  case irm_Z:
+    *fail = (   (mpz_cmp_si (&tv->u.Z, tv_val_chil(mode_l->max)) > 0)
+            || (mpz_cmp_si (&tv->u.Z, tv_val_chil(mode_l->min)) < 0));
+    return mpz_get_si (&tv->u.Z);
+    /* strange */
+  case irm_b:
+    *fail = 0;
+    return tv->u.b;
+  default: ;
+    *fail = 1;
+    return 0;
+  }
+}
+
+
+\f
+int
+tarval_print (XP_PAR1, const xprintf_info *info ATTRIBUTE((unused)), XP_PARN)
+{
+  tarval *val = XP_GETARG (tarval *, 0);
+  int printed;
+
+  TARVAL_VRFY (val);
+
+  switch (val->mode->code) {
+
+  case irm_T:                  /* none */
+    printed = XPSR ("<bad>");
+    break;
+
+  case irm_f:                  /* float */
+    printed = XPF1R ("%g", (double)(val->u.f));
+    break;
+  case irm_d:                  /* double */
+    printed = XPF1R ("%g", (double)(val->u.d));
+    break;
+
+  case irm_c:                  /* signed char */
+  case irm_C:                  /* unsigned char */
+    if (isprint (val->u.chil)) {
+      printed = XPF1R ("'%c'", val->u.chil);
+    } else {
+      printed = XPF1R ("'\\%03o'", val->u.chil);
+    }
+    break;
+
+  case irm_h: case irm_i: case irm_l: /* signed num */
+    printed = XPF1R ("%ld", (long)val->u.chil);
+    break;
+  case irm_H: case irm_I: case irm_L: /* unsigned num */
+    printed = XPF1R ("%lu", (unsigned long)val->u.CHIL);
+    break;
+
+  case irm_Z:                  /* mp int */
+    printed = XPF1R ("%Z", &val->u.Z);
+    break;
+
+  case irm_p:                  /* pointer */
+    if (val->u.p.xname) {
+      printed = XPR (val->u.p.xname);
+    } else if (val->u.p.ent) {
+      printed = XPF1R ("(%I)", val->u.p.ent->name);
+    } else {
+      assert (val == tarval_p_void);
+      printed = XPSR ("(void)");
+    }
+    break;
+
+  case irm_b:                  /* boolean */
+    if (val->u.b) printed = XPSR ("true");
+    else         printed = XPSR ("false");
+    break;
+
+  case irm_B:                  /* universal bits */
+    printed = XPSR ("<@@@ some bits>");
+    break;
+
+  case irm_s:                  /* string */
+  case irm_S:
+    { size_t i;
+      char *buf = alloca (val->u.s.n + 2);
+      char *bp;
+
+      printed = 0;
+      buf[0] = '\'';
+      bp = buf + 1;
+      for (i = 0;  i < val->u.s.n;  ++i) {
+       if (isprint (val->u.s.p[i])) {
+         *bp++ = val->u.s.p[i];
+       } else {
+         if (bp != buf) {
+           XPM (buf, bp-buf);
+           bp = buf;
+         }
+         XPF1 ("'\\%03o'", val->u.s.p[i]);
+       }
+      }
+      *bp++ = '\'';
+      XPM (buf, bp-buf);
+      break;
+    }
+
+
+  case irm_M:                  /* memory */
+  case irm_R:                  /* region */
+  default:
+    assert (0);
+  }
+
+  return printed;
+}
+
+\f
+/* Labeling of tarvals */
+
+label
+tarval_label (tarval *tv)
+{
+  if (!tv->lab) {
+    tv->lab = new_label();
+    tv->used = 1;
+  }
+  return tv->lab;
+}
+
+
+void
+tarval_forall_labeled (int (*f) (tarval *, void *), void *data)
+{
+  tarval *tv;
+
+  for (tv = pset_first (tarvals);  tv;  tv = pset_next (tarvals)) {
+    if (tv->lab && f (tv, data)) {
+      pset_break (tarvals);
+      return;
+    }
+  }
+}
+
+
+ir_mode *
+get_tv_mode (tarval *tv)
+{
+  return tv->mode;
+}
diff --git a/ir/tv/tv.h b/ir/tv/tv.h
new file mode 100644 (file)
index 0000000..ba68f29
--- /dev/null
@@ -0,0 +1,173 @@
+/* Declarations for Target Values.
+   Copyright (C) 1995, 1996 Christian von Roques */
+
+#ifndef _TV_H
+#define _TV_H
+
+# include "irmode.h"
+# include "entity.h"
+# include "label.h"
+# include "xprintf.h"
+
+typedef struct tarval tarval;
+
+#include <gmp.h>
+#undef __need_size_t           /* erroneously defined by 1.3.2's gmp.h */
+/* #include "deftab.h" */
+
+/* how to represent target types on host */
+typedef float tarval_f;
+typedef double tarval_d;
+typedef long tarval_chil;
+typedef unsigned long tarval_CHIL;
+typedef MP_INT tarval_Z;
+typedef struct {
+  /* if ent then xname is missing or mangled from ent,
+     else if xname then xname is a linker symbol that is not mangled
+       from an entity,
+     else this is tarval_p_void.
+     if this tarval describes a symbolic address of another tarval, tv points
+     to this val */
+  const char *xname;
+  entity *ent;
+  tarval *tv;
+} tarval_p;
+typedef struct {
+  unsigned char *p;            /* may contain embedded 0, not 0-terminated */
+  size_t n;
+} tarval_s;
+typedef tarval_s tarval_B;
+
+struct tarval {
+  union {
+    tarval_f f;                        /* float */
+    tarval_d d;                        /* double */
+    tarval_chil chil;          /* signed integral */
+    tarval_CHIL CHIL;          /* unsigned integral */
+    tarval_Z Z;                 /* universal int */
+    tarval_p p;                        /* pointer */
+    bool b;                    /* boolean */
+    tarval_B B;                        /* universal bits */
+    tarval_s s;                        /* string */
+  } u;
+  label lab;                   /* value's label in the constant segment */
+  ir_mode *mode;
+  bool used;                   /* labeled tv is used (default) */
+};
+
+extern tarval *tarval_bad;
+extern tarval *tarval_b_false;
+extern tarval *tarval_b_true;
+extern tarval *tarval_d_NaN;
+extern tarval *tarval_d_Inf;
+extern tarval *tarval_p_void;
+extern tarval *tarval_mode_null[];
+extern tarval *tarval_mode_min[];
+extern tarval *tarval_mode_max[];
+
+void tarval_init_1 (void);
+void tarval_init_2 (void);
+
+/* Hash function on tarvals */
+unsigned tarval_hash (tarval *);
+
+/************************* Constructors for tarvals *************************/
+tarval *tarval_Z_from_str (const char *, size_t, int base);
+tarval *tarval_B_from_str (const char *, size_t);
+tarval *tarval_d_from_str (const char *, size_t);
+tarval *tarval_s_from_str (const char *, size_t);
+tarval *tarval_S_from_str (const char *, size_t);
+tarval *tarval_from_long (ir_mode *, long);
+tarval *tarval_p_from_str (const char *);
+tarval *tarval_p_from_entity (entity *);
+
+tarval *tarval_convert_to (tarval *, ir_mode *);
+
+/* Building an irm_C, irm_s, irm_S or irm_B target value step by step. */
+void tarval_start (void);
+void tarval_append (const char *, size_t);
+void tarval_append1 (char);
+tarval *tarval_finish_as (ir_mode *);
+tarval *tarval_cancel (void); /* returns tarval_bad */
+
+\f
+/* The flags for projecting a comparison result */
+typedef enum {
+  irpn_False=0,                /* false */
+  irpn_Eq,             /* equal */
+  irpn_Lt,             /* less */
+  irpn_Le,             /* less or equal */
+  irpn_Gt,             /* greater */
+  irpn_Ge,             /* greater of equal */
+  irpn_Lg,             /* less or greater */
+  irpn_Leg,            /* less, equal or greater = ordered */
+  irpn_Uo,             /* unordered */
+  irpn_Ue,             /* unordered or equal */
+  irpn_Ul,             /* unordered or less */
+  irpn_Ule,            /* unordered, less or equal */
+  irpn_Ug,             /* unordered or greater */
+  irpn_Uge,            /* unordered, greater or equal */
+  irpn_Ne,             /* unordered, less or greater = not equal */
+  irpn_True,           /* true */
+  irpn_notmask = irpn_Leg
+} ir_pncmp;
+
+/********************* Arithmethic operations on tarvals *********************/
+/* Compare a with b and return an ir_pncmp describing the relation
+   between a and b.  This is either Uo, Lt, Eq, Gt, or False if a or b
+   are symbolic pointers which can not be compared at all. */
+ir_pncmp tarval_comp (tarval *a, tarval *b);
+
+tarval *tarval_neg (tarval *a);
+tarval *tarval_add (tarval *, tarval *);
+tarval *tarval_sub (tarval *, tarval *);
+tarval *tarval_mul (tarval *, tarval *);
+tarval *tarval_quo (tarval *, tarval *);
+tarval *tarval_div (tarval *, tarval *);
+tarval *tarval_mod (tarval *, tarval *);
+tarval *tarval_and (tarval *, tarval *);
+tarval *tarval_or  (tarval *, tarval *);
+tarval *tarval_eor (tarval *, tarval *);
+tarval *tarval_shl (tarval *, tarval *);
+tarval *tarval_shr (tarval *, tarval *);
+
+/* Identifying some tarvals */
+long tarval_classify (tarval *);
+long tarval_ord (tarval *, int *fail);
+
+int tarval_print (XP_PAR1, const xprintf_info *, XP_PARN);
+
+
+     /* Labeling of tarvals */
+label tarval_label (tarval *);
+void tarval_forall_labeled (int (*) (tarval *, void *), void *);
+
+
+/* return a mode-specific value */
+
+tarval_f tv_val_f (tarval *tv);
+tarval_d tv_val_d (tarval *tv);
+tarval_chil tv_val_chil (tarval *tv);
+tarval_CHIL tv_val_CHIL (tarval *tv);
+tarval_Z tv_val_Z (tarval *tv);
+tarval_p tv_val_p (tarval *tv);
+bool tv_val_b (tarval *tv);
+tarval_B tv_val_B (tarval *tv);
+tarval_s tv_val_s (tarval *tv);
+
+#ifdef NDEBUG
+#define TARVAL_VRFY(val) ((void)0)
+#else
+#define TARVAL_VRFY(val) _tarval_vrfy ((val))
+extern void _tarval_vrfy (const tarval *);
+#endif
+
+#ifdef STATS
+void tarval_stats (void);
+#else
+#define tarval_stats() ((void)0)
+#endif
+
+ir_mode *get_tv_mode (tarval *tv);
+
+#endif
diff --git a/testprograms/Makefile b/testprograms/Makefile
new file mode 100644 (file)
index 0000000..0c2673d
--- /dev/null
@@ -0,0 +1,93 @@
+
+DIRS = adt common debug ident ir tr tv
+INCDIRS = $(DIRS:%=-I../ir/%)
+
+LIBDIRS=-L.. -L/usr/public/lib/gmp/
+LIBS=-lfirm -lgmp -lm
+
+%.o:   %.c
+       gcc -c $(INCDIRS) $<
+
+all: empty const_eval_example                                  \
+     if_example if_else_example if_while_example cond_example  \
+     call_str_example memory_example array-stack_example       \
+     array-heap_example oo_program_example irr_cf_example      \
+     irr_loop_example dead_block_example
+
+clean:
+       rm -f                                   \
+       empty.o empty                           \
+       const_eval_example.o const_eval_example \
+       if_example.o if_example                 \
+       if_else_example.o if_else_example       \
+       if_while_example.o if_while_example     \
+       cond_example.o cond_example             \
+       call_str_example.o call_str_example     \
+       memory_example.o memory_example         \
+       array-stack_example.o array-stack_example       \
+       array-heap_example.o array-heap_example \
+       oo_program_example.o oo_program_example \
+       irr_cf_example.o irr_cf_example         \
+       irr_loop_example.o irr_loop_example     \
+       dead_block_example.o dead_block_example \
+       *.vcg core
+
+realclean:     clean
+
+run:
+       ./empty;                \
+       const_eval_example      \
+       if_example;             \
+       if_else_example         \
+       if_while_example;       \
+       cond_example            \
+       call_str_example;       \
+       memory_example          \
+       array-stack_example;    \
+       array-heap_example;     \
+       oo_program_example;     \
+       irr_cf_example;         \
+       irr_loop_example;       \
+       dead_block_example;
+
+empty: empty.o
+       gcc -o empty empty.o $(LIBDIRS) $(LIBS)
+
+const_eval_example: const_eval_example.o
+       gcc -o const_eval_example const_eval_example.o $(LIBDIRS) $(LIBS)
+
+if_example: if_example.o
+       gcc -o if_example if_example.o $(LIBDIRS) $(LIBS)
+
+if_else_example: if_else_example.o
+       gcc -o if_else_example if_else_example.o $(LIBDIRS) $(LIBS)
+
+if_while_example: if_while_example.o
+       gcc -o if_while_example if_while_example.o $(LIBDIRS) $(LIBS)
+
+cond_example: cond_example.o
+       gcc -o cond_example cond_example.o $(LIBDIRS) $(LIBS)
+
+call_str_example: call_str_example.o
+       gcc -o call_str_example call_str_example.o $(LIBDIRS) $(LIBS)
+
+memory_example: memory_example.o
+       gcc -o memory_example memory_example.o $(LIBDIRS) $(LIBS)
+
+array-stack_example: array-stack_example.o
+       gcc -o array-stack_example array-stack_example.o $(LIBDIRS) $(LIBS)
+
+array-heap_example: array-heap_example.o
+       gcc -o array-heap_example array-heap_example.o $(LIBDIRS) $(LIBS)
+
+oo_program_example: oo_program_example.o
+       gcc -o oo_program_example oo_program_example.o $(LIBDIRS) $(LIBS)
+
+irr_cf_example: irr_cf_example.o
+       gcc -o irr_cf_example irr_cf_example.o $(LIBDIRS) $(LIBS)
+
+irr_loop_example: irr_loop_example.o
+       gcc -o irr_loop_example irr_loop_example.o $(LIBDIRS) $(LIBS)
+
+dead_block_example: dead_block_example.o
+       gcc -o dead_block_example dead_block_example.o $(LIBDIRS) $(LIBS)
diff --git a/testprograms/array-heap_example.c b/testprograms/array-heap_example.c
new file mode 100644 (file)
index 0000000..084378a
--- /dev/null
@@ -0,0 +1,153 @@
+ /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+# include "irdump.h"
+# include "firm.h"
+
+/**  This example describes a possible representation of heap allocated
+***  variables of imperative programs.
+***  It constructs the IR for the following program:
+***
+***
+***  main(): int
+***    int *a[10];
+***
+***    a = malloc(sizeof(a[10]));
+***    return (a[3]);
+***  end;
+***
+***  The array is placed on the heap.  The pointer to the array that
+***  is a local variable is represented as a dataflow edge.
+***  There are two ways to model allocation to the heap in programs with
+***  explicit memory allocation:
+***  1. Model the calls to malloc and free as simple procedure (of compiler
+***     known procedures returning a pointer.  This is the simpler way of
+***     generating FIRM, but restricts the information that can be deduced
+***     for the call.
+***  2. Insert an Alloc node.  A later pass can lower this to the compiler
+***     known function.  This makes the allocation explicit in FIRM, supporting
+***     optimization.
+***     A problem is modeling free.  There is no free node in FIRM.  Is this
+***     a necessary extension?
+***  This example shows the second alternative, where the size of the array
+***  is explicitly computed.
+**/
+
+#define OPTIMIZE_NODE 0
+
+int
+main(void)
+{
+  /* describes the fake class "ARRAY-HEAP_EXAMPLE" with it's method main */
+  type_class     *owner;
+  type_method    *proc_main;
+  entity         *proc_main_e;
+
+  /* describes types defined by the language */
+  type_primitive *prim_t_int;
+
+  /* describes the array and its fields. */
+  type_array     *array_type;   /* the type information for the array */
+  entity         *array_ent;    /* the entity representing a field of the array */
+
+  /* Needed while finding the element size.  */
+  type_primitive *elt_type;
+  ir_mode        *elt_type_mode;
+  int            size;
+  ir_node        *arr_size;
+
+  /* holds the graph and nodes. */
+  ir_graph       *main_irg;
+  ir_node        *array, *array_ptr, *c3, *elt, *val, *x;
+
+
+  init_firm ();
+
+  /* make basic type information for primitive type int.
+     In Sather primitive types are represented by a class.
+     This is the modeling appropriate for other languages.
+     Mode_i says that all integers shall be implemented as a
+     32 bit integer value.  */
+  prim_t_int = new_type_primitive(id_from_str ("int", 3), mode_i);
+
+  printf("creating an IR graph: ARRAY-HEAP_EXAMPLE...\n");
+
+  /* first build procedure main */
+  owner = new_type_class (id_from_str ("ARRAY-HEAP_EXAMPLE", 13));
+  proc_main = new_type_method(id_from_str("main", 4), 0, 1);
+  set_method_res_type(proc_main, 0, (type *)prim_t_int);
+  proc_main_e = new_entity ((type*)owner, id_from_str ("main", 4), (type *)proc_main);
+  main_irg = new_ir_graph (proc_main_e, 4);
+
+  /* make type information for the array and set the bounds */
+# define N_DIMS 1
+# define L_BOUND 0
+# define U_BOUND 9
+  array_type = new_type_array(id_from_str("a", 1), N_DIMS);
+  set_array_bounds(array_type, 1, L_BOUND, U_BOUND);
+  set_array_element_type(array_type, (union type*)prim_t_int);
+  /* As the array is accessed by Sel nodes, we need information about
+     the entity the node select.  Entities of an array are it's elements
+     which are, in this case, integers. */
+  array_ent = new_entity((type*)array_type, id_from_str("array_field", 11), (type*)prim_t_int);
+
+  /* Allocate the array. All program known variables that
+     are not modeled by dataflow edges need an explicit allocate node.
+     If the variable shall be placed on the stack, set stack_alloc.  */
+  /*   first compute size in bytes. */
+  elt_type = (type_primitive *)get_array_element_type(array_type);
+  if (! (elt_type->kind == k_type_primitive)) printf(" do something else\n");
+  elt_type_mode = get_primitive_mode(elt_type);
+  /*   better: read bounds out of array type information */
+  size = (U_BOUND - L_BOUND + 1) * elt_type_mode->size;
+  /*   make constant representing the size */
+  arr_size  = new_Const(mode_I, tarval_from_long (mode_I, size));
+  /*   allocate and generate the Proj nodes. */
+  array     = new_Alloc(get_store(), arr_size, (type*)array_type, stack_alloc);
+  set_store(new_Proj(array, mode_M, 0));   /* make the changed memory visible */
+  array_ptr = new_Proj(array, mode_p, 1);  /* remember the pointer to the array */
+
+  /* Now the "real" program: */
+  /* Load element 3 of the array. For this first generate the pointer to this
+     array element by a select node.  (Alternative: increase array pointer
+     by (three * elt_size), but this complicates some optimizations. The
+     type information accessible via the entity allows to generate the
+     pointer increment later. */
+  c3 = new_Const (mode_I, tarval_from_long (mode_I, 3));
+  {
+     ir_node *in[1];
+     in[0] = c3;
+     elt = new_Sel(get_store(), array_ptr, 1, in, array_ent);
+  }
+  val = new_Load(get_store(), elt);
+  set_store(new_Proj(val, mode_M, 0));
+  val = new_Proj(val, mode_i, 1);
+
+  /* return the result of procedure main */
+  {
+     ir_node *in[1];
+     in[0] = val;
+
+     x = new_Return (get_store (), 1, in);
+  }
+  mature_block (main_irg->current_block);
+
+  /* complete the end_block */
+  add_in_edge (main_irg->end_block, x);
+  mature_block (main_irg->end_block);
+
+  printf("\nDone building the graph.\n");
+  printf("Dumping the graph and a type graph.\n");
+  dump_ir_block_graph (main_irg);
+  dump_type_graph(main_irg);
+
+  printf("\nuse xvcg to view these graphs:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (1);
+}
diff --git a/testprograms/array-stack_example.c b/testprograms/array-stack_example.c
new file mode 100644 (file)
index 0000000..f23d080
--- /dev/null
@@ -0,0 +1,139 @@
+ /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+# include "irdump.h"
+# include "firm.h"
+
+/**  This example describes representation of stack allocated variables of
+***  imperative programs.
+***  It constructs the IR for the following program:
+***
+***
+***  main(): int
+***    int a[10];
+***
+***    return (a[3]);
+***  end;
+***
+***  The array is placed on the stack, i.e., a pointer to the array
+***  is obtained by selecting the entity "a" from the stack.  The variables
+***  on the stack are considered to be entities of the method, as locals
+***  of a method are only visible within the method.  (An alternative to
+***  make the method owner of the stack variables is to give the ownership
+***  to the class representing the C-file.  This would extend the visibility
+***  of the locals, though.)
+**/
+
+
+#define OPTIMIZE_NODE 0
+
+int
+main(void)
+{
+  /* describes the general structure of a C-file */
+  type_class     *owner;        /* the class standing for everything in this file */
+  type_method    *proc_main;    /* Typeinformation for method main. */
+  entity         *proc_main_e;  /* The entity describing that method main is an
+                                   entity of the fake class representing the file. */
+
+  /* describes types defined by the language */
+  type_primitive *prim_t_int;
+
+  /* describes the array and its fields. */
+  entity         *array_ent;    /* the entity representing the array as member
+                                   of the stack/method */
+  type_array     *array_type;   /* the type information for the array */
+  entity         *field_ent;    /* the entity representing a field of the array */
+
+  /* Needed while finding the element size.  */
+  type_primitive *elt_type;
+  ir_mode        *elt_type_mode;
+  int            size;
+  ir_node        *arr_size;
+
+  /* holds the graph and nodes. */
+  ir_graph       *main_irg;
+  ir_node        *array, *array_ptr, *c3, *elt, *val, *x;
+
+
+  init_firm ();
+
+  printf("creating an IR graph: ARRAY-STACK_EXAMPLE...\n");
+
+  /* make basic type information for primitive type int.
+     In Sather primitive types are represented by a class.
+     This is the modeling appropriate for other languages.
+     Mode_i says that all language-integers shall be implemented
+     as a 32 bit processor-integer value.  */
+  prim_t_int = new_type_primitive(id_from_str ("int", 3), mode_i);
+
+  /* build typeinformation of procedure main */
+  owner = new_type_class (id_from_str ("ARRAY-STACK_EXAMPLE", 19));
+  proc_main = new_type_method(id_from_str("main", 4), 0, 1);
+  set_method_res_type(proc_main, 0, (type *)prim_t_int);
+  proc_main_e = new_entity ((type*)owner, id_from_str ("main", 4), (type *)proc_main);
+
+  main_irg = new_ir_graph (proc_main_e, 4);
+
+  /* make type information for the array and set the bounds */
+# define N_DIMS 1
+# define L_BOUND 0
+# define U_BOUND 9
+  array_type = new_type_array(id_from_str("a", 1), N_DIMS);
+  set_array_bounds(array_type, 1, L_BOUND, U_BOUND);
+  set_array_element_type(array_type, (type*)prim_t_int);
+  /* The array is an entity of the method, placed on the mehtod's own memory,
+     the stack frame. */
+  array_ent = new_entity((type *)proc_main, id_from_str("a", 1), (type *)array_type);
+  /* As the array is accessed by Sel nodes, we need information about
+     the entity the node select.  Entities of an array are it's elements
+     which are, in this case, integers. */
+  /* change entity owner types.   */
+  field_ent = new_entity((type*)array_type, id_from_str("array_field", 11), (type*)prim_t_int);
+
+  /* Now the "real" program: */
+  /* Select the array from the stack frame.  */
+  array_ptr = new_simpleSel(get_store(), main_irg->frame, array_ent);
+  /* Load element 3 of the array. For this first generate the pointer
+     to this the element by a select node.  (Alternative: increase
+     array pointer by (three * elt_size), but this complicates some
+     optimizations.) The type information accessible via the entity
+     allows to generate the pointer increment later. */
+  c3 = new_Const (mode_I, tarval_from_long (mode_I, 3));
+  {
+     ir_node *in[1];
+     in[0] = c3;
+     elt = new_Sel(get_store(), array_ptr, 1, in, field_ent);
+  }
+  val = new_Load(get_store(), elt);
+  set_store(new_Proj(val, mode_M, 0));
+  val = new_Proj(val, mode_i, 1);
+
+  /* return the result of procedure main */
+  {
+     ir_node *in[1];
+     in[0] = val;
+
+     x = new_Return (get_store (), 1, in);
+  }
+  mature_block (main_irg->current_block);
+
+  /* complete the end_block */
+  add_in_edge (main_irg->end_block, x);
+  mature_block (main_irg->end_block);
+
+  printf("\nDone building the graph.\n");
+  printf("Dumping the graph and a type graph.\n");
+  dump_ir_block_graph (main_irg);
+  dump_type_graph(main_irg);
+
+  printf("\nuse xvcg to view these graphs:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (1);
+}
diff --git a/testprograms/call_str_example.c b/testprograms/call_str_example.c
new file mode 100644 (file)
index 0000000..6d78e37
--- /dev/null
@@ -0,0 +1,104 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+#include <stdio.h>
+
+# include "irdump.h"
+# include "firm.h"
+
+/**
+***  This file constructs the ir for the following pseudo-program:
+***
+***  void f(char *);
+***
+***  main() {
+***    f("Hello world !");
+***  }
+**/
+
+int main(int argc, char **argv)
+{
+  ir_graph *irg;          /* this variable contains the irgraph */
+  type_class *owner;      /* the class in which this method is defined */
+  entity *ent;            /* represents this method as entity of owner */
+  ir_node *x, *const_str, *proc_ptr, *call;
+
+  printf("creating an IR graph: CALL_STR_EXAMPLE...\n");
+
+  /* init library */
+  init_firm ();
+
+  /* FIRM was designed for oo languages where all methods belong to a class.
+   * For imperative languages like C we view a file as a large class containing
+   * all functions as methods in this file.
+   * Therefore we define a class "CALL_STR_EXAMPLE" with a method main as
+   * an entity.
+   */
+#define CLASSNAME "CALL_STR_EXAMPLE"
+#define ENTITYNAME "main"
+
+  owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
+  ent = new_entity ((type *)owner, id_from_str (ENTITYNAME, strlen(ENTITYNAME)), NULL);
+
+
+  /* Generates the basic graph for the method represented by entity ent, that
+   * is, generates start and end blocks and nodes and a first, initial block.
+   * The constructor needs to know how many local variables the method has.
+   */
+#define NUM_OF_LOCAL_VARS 0
+
+  irg = new_ir_graph (ent, NUM_OF_LOCAL_VARS);
+
+  /* the string is enterd in the constant table. const_str is a pointer to the string */
+  const_str = new_Const (mode_p, tarval_p_from_str ("Hello world!"));
+
+  /* get the pointer to the procedure from the class type */
+  /* this is how a pointer to be fixed by the linker is represented after
+     lowering a Sel node. */
+#define FUNCTIONNAME "f"
+  proc_ptr = new_Const (mode_p, tarval_p_from_str (FUNCTIONNAME));
+
+  /* call procedure set_a, first built array with parameters */
+  {
+    ir_node *in[1];
+    in[0] = const_str;
+    call = new_Call(get_store(), proc_ptr, 1, in, NULL);
+  }
+  /* make the possible change of call to memory visible */
+  set_store(new_Proj(call, mode_M, 0));
+
+
+  /* The constructor new_ir_graph() generated a region to place nodes in.
+   * This region is accessible via the attribut current_block of irg and
+   * it is not matured.
+   * Generate the return node into this region. The Return node is needed to
+   * return at least the store. */
+  {
+    ir_node *in[0]; /* this is the array containing the return parameters */
+    x = new_Return (get_store(), 0, in);
+  }
+  /* Now generate all instructions for this block and all its predecessor blocks
+   * so we can mature it. */
+  mature_block (irg->current_block);
+
+  /* This adds the in edge of the end block which originates at the return statement.
+   * The return node passes controlflow to the end block.  */
+  add_in_edge (irg->end_block, x);
+  /* Now we can mature the end block as all it's predecessors are known. */
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph.  Dumping it.\n");
+  dump_ir_block_graph (irg);
+
+  printf("use xvcg to view this graph:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+
+
+}
diff --git a/testprograms/cond_example.c b/testprograms/cond_example.c
new file mode 100644 (file)
index 0000000..96e9bf1
--- /dev/null
@@ -0,0 +1,125 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+#include <stdio.h>
+
+# include "irdump.h"
+# include "firm.h"
+
+/**
+***  This file constructs the ir for the following pseudo-program:
+***
+***  main(int a) {
+***    if ((a > 2) && (a < 10))
+***      { a = 1; }
+***
+***    return a;
+**/
+
+int main(int argc, char **argv)
+{
+  ir_graph *irg;          /* this variable contains the irgraph */
+  type_class *owner;      /* the class in which this method is defined */
+  entity *ent;            /* represents this method as entity of owner */
+  ir_node *x, *x_then, *arg1, *c2, *c10, *cmpGt, *cmpLt, *and, *f, *t, *b;
+
+  printf("creating an IR graph: COND_EXAMPLE...\n");
+
+  /* init library */
+  init_firm ();
+
+  /* FIRM was designed for oo languages where all methods belong to a class.
+   * For imperative languages like C we view a file as a large class containing
+   * all functions as methods in this file.
+   * Therefore we define a class "COND_EXAMPLE" with a method main as an
+   * entity.
+   */
+#define CLASSNAME "COND_EXAMPLE"
+#define ENTITYNAME "main"
+
+  owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
+  ent = new_entity ((type *)owner, id_from_str (ENTITYNAME, strlen(ENTITYNAME)), NULL);
+
+
+  /* Generates the basic graph for the method represented by entity ent, that
+   * is, generates start and end blocks and nodes and a first, initial block.
+   * The constructor needs to know how many local variables the method has.
+   */
+#define NUM_OF_LOCAL_VARS 1
+
+  irg = new_ir_graph (ent, NUM_OF_LOCAL_VARS);
+
+  /* get the first argument a of method main - see irgraph.h */
+  arg1 = new_Proj(irg->args, mode_i, 0);
+
+  /* arg1 as first first local variable - makes things simple */
+  set_value(0, arg1);
+
+  /* the expression that evaluates the condition */
+  /* cmpGt = a > 2 */
+  c2 = new_Const (mode_i, tarval_from_long (mode_i, 2));
+  cmpGt = new_Proj(new_Cmp(get_value(0, mode_i), c2), mode_b, Gt);
+  cmpGt = new_Conv(cmpGt, mode_i);
+
+  /* cmpLt = a < 10 */
+  c10 = new_Const (mode_i, tarval_from_long (mode_i, 10));
+  cmpLt = new_Proj(new_Cmp(get_value(0, mode_i), c10), mode_b, Lt);
+  cmpLt = new_Conv(cmpLt, mode_i);
+
+  /* cmpGt && cmpLt */
+  and = new_And(cmpGt, cmpLt, mode_i);
+  /* compare result and 0 because we have no cast from integer to bool */
+  and = new_Cmp(and, new_Const (mode_i, tarval_from_long (mode_i, 0)));
+  and = new_Proj(and, mode_b, Ne);
+
+  /* the conditional branch */
+  x = new_Cond (and);
+  f = new_Proj (x, mode_X, 0); /* if condition is false */
+  t = new_Proj (x, mode_X, 1); /* if condition is true */
+
+  mature_block (irg->current_block);
+
+  /* generate and fill the then block */
+  b = new_Block ();
+  add_in_edge (b, t);
+  set_value (0, new_Const (mode_i, tarval_from_long (mode_i, 1)));
+  mature_block (b);
+  x_then = new_Jmp ();
+
+  /* generate the fall through block and add all cfg edges */
+  b = new_Block ();
+  add_in_edge (b, x_then);
+  add_in_edge (b, f);
+
+
+  /* Generate the return node into current region. */
+  {
+    ir_node *in[1]; /* this is the array containing the return parameters */
+    in[0] = get_value(0, mode_i);
+    x = new_Return (get_store(), 1, in);
+  }
+  /* Now generate all instructions for this block and all its predecessor blocks
+   * so we can mature it. */
+  mature_block (irg->current_block);
+
+  /* This adds the in edge of the end block which originates at the return statement.
+   * The return node passes controlflow to the end block.  */
+  add_in_edge (irg->end_block, x);
+  /* Now we can mature the end block as all it's predecessors are known. */
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph.  Dumping it.\n");
+  dump_ir_block_graph (irg);
+
+  printf("use xvcg to view this graph:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+
+
+}
diff --git a/testprograms/const_eval_example.c b/testprograms/const_eval_example.c
new file mode 100644 (file)
index 0000000..036e98c
--- /dev/null
@@ -0,0 +1,77 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram
+*/
+
+# include "irdump.h"
+# include "firm.h"
+
+/**
+***  This file constructs the ir for the following pseudo-program:
+***
+***  main() {
+***    int c, d;
+***
+***    c = 5 + 7;
+***    d = 7 + 5;
+***
+***    return (c, d);
+***  }
+**/
+
+int
+main(void)
+{
+  ir_graph *irg;
+  type_class *owner;
+  entity *ent;
+  ir_node *a, *b, *c, *d, *x;
+
+  printf("creating an IR graph: CONST_EVAL_EXAMPLE...\n");
+
+  init_firm ();
+
+  /* Try both optimizations: */
+  set_opt_constant_folding(1);
+  set_opt_cse(1);
+
+  owner = new_type_class (id_from_str ("CONST_EVAL_EXAMPLE", 18));
+  ent = new_entity ((type *)owner, id_from_str ("main", 4), NULL);
+
+  irg = new_ir_graph (ent, 4);
+
+  a = new_Const (mode_i, tarval_from_long (mode_i, 5));
+  b = new_Const (mode_i, tarval_from_long (mode_i, 7));
+
+  x = new_Jmp ();
+  mature_block (irg->current_block);
+
+  c = new_Add (new_Const (mode_i, tarval_from_long (mode_i, 5)),
+              new_Const (mode_i, tarval_from_long (mode_i, 7)),
+              mode_i);
+  d = new_Add (new_Const (mode_i, tarval_from_long (mode_i, 7)),
+              new_Const (mode_i, tarval_from_long (mode_i, 5)),
+              mode_i);
+
+  {
+     ir_node *in[2];
+     in[0] = c;
+     in[1] = d;
+
+     x = new_Return (get_store (), 2, in);
+  }
+
+  add_in_edge (irg->end_block, x);
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph.  Dumping it.\n");
+  dump_ir_block_graph (irg);
+
+  printf("use xvcg to view this graph:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+}
diff --git a/testprograms/dead_block_example.c b/testprograms/dead_block_example.c
new file mode 100644 (file)
index 0000000..2ff7b31
--- /dev/null
@@ -0,0 +1,135 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+# include <stdio.h>
+
+# include "irdump.h"
+# include "firm.h"
+
+/*
+ *   a dead block / unreachable code.
+ */
+
+/**
+***  This file constructs a control flow of following shape:
+***
+***
+***         firstBlock
+***          /   \
+***         /     \
+***       |/_     _\|
+***     Block1    Block2   deadBlock
+***        \       |       /
+***        \      |      /
+***        _\|   \ /   |/_
+***            nextBlock
+***
+***
+***   This is a program as, e.g.,
+***
+***   if () then
+***     { Jmp label1; } // happens anyways
+***   else
+***     { Jmp label1; } // happens anyways
+*** label1:
+***   return();
+***   Jmp label1;
+***
+**/
+
+int main(int argc, char **argv)
+{
+  ir_graph *irg;          /* this variable contains the irgraph */
+  type_class *owner;      /* the class in which this method is defined */
+  type_method *proc_main; /* typeinformation for the method main */
+  entity *ent;            /* represents this method as entity of owner */
+  ir_node *c1, *c2, *cond, *f, *t, *endBlock, *Block1, *jmp, *Block2,
+          *deadBlock, *x;
+
+
+  /* init library */
+  init_firm ();
+  set_opt_constant_folding (1);
+
+  /* FIRM was designed for oo languages where all methods belong to a class.
+   * For imperative languages like C we view a file as a large class containing
+   * all functions as methods in this file.
+   * Therefore we define a class "empty" according to the file name
+   * with a method main as an entity.
+   */
+#define CLASSNAME "DEAD_BLOCK"
+#define METHODNAME "main"
+#define NRARGS 0
+#define NRES 0
+  printf("creating an IR graph: %s...\n", CLASSNAME);
+
+  owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
+  proc_main = new_type_method(id_from_str(METHODNAME, strlen(METHODNAME)),
+                              NRARGS, NRES);
+  ent = new_entity ((type *)owner,
+                    id_from_str (METHODNAME, strlen(METHODNAME)),
+                    (type *)proc_main);
+
+#define NUM_OF_LOCAL_VARS 1
+
+  irg = new_ir_graph (ent, NUM_OF_LOCAL_VARS);
+
+  /* two make a condition  */
+  c1 = new_Const (mode_i, tarval_from_long (mode_i, 1));
+  c2 = new_Const (mode_i, tarval_from_long (mode_i, 2));
+
+  cond = new_Cond(new_Proj(new_Cmp(c1, c2), mode_b, Eq));
+  f = new_Proj(cond, mode_X, 0);
+  t = new_Proj(cond, mode_X, 1);
+  mature_block(irg->current_block);
+
+  /* end block to add jmps */
+  endBlock = new_Block();
+
+  /* Block 1 */
+  Block1 = new_Block();
+  add_in_edge(Block1, t);
+  mature_block(Block1);
+  jmp = new_Jmp();
+  add_in_edge(endBlock, jmp);
+
+  /* Block 2 */
+  Block2 = new_Block();
+  add_in_edge(Block2, f);
+  mature_block(Block2);
+  set_value(0, c2);
+  jmp = new_Jmp();
+  add_in_edge(endBlock, jmp);
+
+  /* dead Block */
+  deadBlock = new_Block();
+  mature_block(deadBlock);
+  jmp = new_Jmp();
+  add_in_edge(endBlock, jmp);
+
+  switch_block(endBlock);
+  {
+    ir_node *in[1];
+    in[0] = get_value(0, mode_i);
+    x = new_Return (get_store(), 1, in);
+  }
+  mature_block (irg->current_block);
+
+  add_in_edge (irg->end_block, x);
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph.\n");
+  printf("Dumping the graph and a control flow graph.\n");
+  dump_ir_block_graph (irg);
+  dump_cfg (irg);
+
+  printf("use xvcg to view these graphs:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+}
diff --git a/testprograms/empty.c b/testprograms/empty.c
new file mode 100644 (file)
index 0000000..5d2e7fc
--- /dev/null
@@ -0,0 +1,94 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+#include <stdio.h>
+
+# include "irdump.h"
+# include "firm.h"
+
+/*
+ * das leere FIRM Programm
+ */
+
+/**
+***  This file constructs the ir for the following pseudo-program:
+***
+***  main() {
+***    return;
+***  }
+**/
+
+int main(int argc, char **argv)
+{
+  ir_graph *irg;          /* this variable contains the irgraph */
+  type_class *owner;      /* the class in which this method is defined */
+  type_method *proc_main; /* typeinformation for the method main */
+  entity *ent;            /* represents this method as entity of owner */
+  ir_node *x;
+
+  printf("creating an IR graph: EMPTY...\n");
+
+  /* init library */
+  init_firm ();
+
+  /* FIRM was designed for oo languages where all methods belong to a class.
+   * For imperative languages like C we view a file as a large class containing
+   * all functions as methods in this file.
+   * Therefore we define a class "empty" according to the file name
+   * with a method main as an entity.
+   */
+#define CLASSNAME "EMPTY"
+#define METHODNAME "main"
+#define NRARGS 0
+#define NRES 0
+
+  owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
+  proc_main = new_type_method(id_from_str(METHODNAME, strlen(METHODNAME)),
+                              NRARGS, NRES);
+  ent = new_entity ((type *)owner,
+                    id_from_str (METHODNAME, strlen(METHODNAME)),
+                    (type *)proc_main);
+
+  /* Generates the basic graph for the method represented by entity ent, that
+   * is, generates start and end blocks and nodes and a first, initial block.
+   * The constructor needs to know how many local variables the method has.
+   */
+#define NUM_OF_LOCAL_VARS 0
+
+  irg = new_ir_graph (ent, NUM_OF_LOCAL_VARS);
+
+
+  /* The constructor new_ir_graph() generated a region to place nodes in.
+   * This region is accessible via the attribut current_block of irg and
+   * it is not matured.
+   * Generate the return node into this region. The Return node is needed to
+   * return at least the store. */
+  {
+    ir_node *in[0]; /* this is the array containing the return parameters */
+    x = new_Return (get_store(), 0, in);
+  }
+  /* Now generate all instructions for this block and all its predecessor blocks
+   * so we can mature it. */
+  mature_block (irg->current_block);
+
+  /* This adds the in edge of the end block which originates at the return statement.
+   * The return node passes controlflow to the end block.  */
+  add_in_edge (irg->end_block, x);
+  /* Now we can mature the end block as all it's predecessors are known. */
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph.  Dumping it.\n");
+  dump_ir_block_graph (irg);
+
+  printf("use xvcg to view this graph:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+
+
+}
diff --git a/testprograms/if_else_example.c b/testprograms/if_else_example.c
new file mode 100644 (file)
index 0000000..8252950
--- /dev/null
@@ -0,0 +1,131 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+#include <stdio.h>
+
+# include "irdump.h"
+# include "firm.h"
+
+/*
+ * das leere FIRM Programm
+ */
+
+/**
+***  This file constructs the ir for the following pseudo-program:
+***
+***  main() {
+***    int a = 0;
+***    int b = 1;
+***
+***    if (a > 2)
+***      { a = b; }
+***    else
+***      { b = 2; }
+***
+***    return a, b;
+**/
+
+int main(int argc, char **argv)
+{
+  ir_graph *irg;          /* this variable contains the irgraph */
+  type_class *owner;      /* the class in which this method is defined */
+  entity *ent;            /* represents this method as entity of owner */
+  ir_node *x, *x_then, *x_else, *c0, *c1, *c2, *cmpGt, *f, *t, *b;
+
+  printf("creating an IR graph: IF_ELSE_EXAMPLE...\n");
+
+  /* init library */
+  init_firm ();
+
+  /* FIRM was designed for oo languages where all methods belong to a class.
+   * For imperative languages like C we view a file as a large class containing
+   * all functions as methods in this file.
+   * Therefore we define a class "IF_ELSE_EXAMPLE" with a method main as an
+   * entity.
+   */
+#define CLASSNAME "IF_ELSE_EXAMPLE"
+#define ENTITYNAME "main"
+
+  owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
+  ent = new_entity ((type *)owner, id_from_str (ENTITYNAME, strlen(ENTITYNAME)), NULL);
+
+
+  /* Generates the basic graph for the method represented by entity ent, that
+   * is, generates start and end blocks and nodes and a first, initial block.
+   * The constructor needs to know how many local variables the method has.
+   */
+#define NUM_OF_LOCAL_VARS 2
+
+  irg = new_ir_graph (ent, NUM_OF_LOCAL_VARS);
+
+  /* Generate two constants */
+  c0 = new_Const (mode_i, tarval_from_long (mode_i, 0));
+  c1 = new_Const (mode_i, tarval_from_long (mode_i, 1));
+
+  /* set a and b to constants */
+  set_value (0, c0);  /* this (0) is variable a */
+  set_value (1, c1);  /* this (1) is variable b */
+
+  /* the expression that evaluates the condition */
+  c2 = new_Const (mode_i, tarval_from_long (mode_i, 2));
+  cmpGt = new_Proj(new_Cmp(get_value(0, mode_i), c2), mode_b, Gt);
+
+  /* the conditional branch */
+  x = new_Cond (cmpGt);
+  f = new_Proj (x, mode_X, 0); /* if condition is false */
+  t = new_Proj (x, mode_X, 1); /* if condition is true */
+
+  mature_block (irg->current_block);
+
+  /* generate and fill the then block */
+  b = new_Block ();
+  add_in_edge (b, t);
+  set_value (0, get_value(1, mode_i));
+  mature_block (b);
+  x_then = new_Jmp ();
+
+  /* generate and fill the else block */
+  b = new_Block ();
+  add_in_edge (b, f);
+  set_value (1, new_Const (mode_i, tarval_from_long (mode_i, 2)));
+  mature_block (b);
+  x_else = new_Jmp ();
+
+  /* generate the join block and add all cfg edges */
+  b = new_Block ();
+  add_in_edge (b, x_then);
+  add_in_edge (b, x_else);
+
+
+  /* Generate the return node into current region. */
+  {
+    ir_node *in[2]; /* this is the array containing the return parameters */
+    in[0] = get_value(0, mode_i);
+    in[1] = get_value(1, mode_i);
+    x = new_Return (get_store(), 2, in);
+  }
+  /* Now generate all instructions for this block and all its predecessor blocks
+   * so we can mature it. */
+  mature_block (irg->current_block);
+
+  /* This adds the in edge of the end block which originates at the return statement.
+   * The return node passes controlflow to the end block.  */
+  add_in_edge (irg->end_block, x);
+  /* Now we can mature the end block as all it's predecessors are known. */
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph.  Dumping it.\n");
+  dump_ir_block_graph (irg);
+
+  printf("use xvcg to view this graph:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+
+
+}
diff --git a/testprograms/if_example.c b/testprograms/if_example.c
new file mode 100644 (file)
index 0000000..d3ca040
--- /dev/null
@@ -0,0 +1,125 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+# include "irdump.h"
+# include "firm.h"
+
+/**
+***  This file constructs the ir for the following pseudo-program:
+***
+***  Doesn't work for some reason!!!!
+***
+***  main() {
+***    int a = 0;
+***    int b = 2;
+***    if ( a == a )  // a constant condition would be eliminated,
+***                   // a realistic condition would no more be a small example
+***      { a := a - 2; }
+***
+***    // return a, bla; // das ist hier kein korrekter graph
+***  }
+**/
+
+int
+main(void)
+{
+  ir_graph *irg;
+  type_class *owner;
+  entity *ent;
+  type_method *proc_main; /* typeinformation for the method main */
+  type_primitive *typ;
+  ir_node *x, *r, *t, *f, *a;
+  int a_pos, b_pos;
+  FILE *outfile;
+
+  printf("creating an IR graph: IF_EXAMPLE...\n");
+
+  init_firm ();
+
+#define CLASSNAME "IF_EXAMPLE"
+#define METHODNAME "main"
+#define NRARGS 0
+#define NRES 2
+
+  owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
+  proc_main = new_type_method(id_from_str(METHODNAME, strlen(METHODNAME)), NRARGS, NRES);
+  ent = new_entity ((type *)owner,
+                    id_from_str (METHODNAME, strlen(METHODNAME)),
+                    (type *)proc_main);
+
+#define RES_NAME "res1"
+  typ = new_type_primitive(ID_FROM_STR(RES_NAME, strlen(RES_NAME)), mode_i);
+  set_method_res_type(proc_main, 0, (type*)typ);
+#undef RES_NAME
+
+#define RES_NAME "res2"
+  typ = new_type_primitive(ID_FROM_STR(RES_NAME, strlen(RES_NAME)), mode_i);
+  set_method_res_type(proc_main, 1, (type*)typ);
+#undef RES_NAME
+
+
+  /* Generates start and end blocks and nodes and a first, initial block */
+  irg = new_ir_graph (ent, 1);
+
+  /* The value position used for a: */
+  a_pos = 0;
+  b_pos = 1;
+
+  /* Generate the constant */
+  set_value (a_pos, new_Const (mode_i, tarval_from_long (mode_i, 0)));
+  set_value (b_pos, new_Const (mode_i, tarval_from_long (mode_i, 2)));
+  mature_block (irg->current_block);
+
+  /* Generate a conditional branch */
+  x = new_Cond (new_Proj(new_Cmp(get_value(a_pos, mode_i),
+                                 get_value(a_pos, mode_i)),
+                         mode_b, Eq));
+  f = new_Proj (x, mode_X, 0);
+  t = new_Proj (x, mode_X, 1);
+
+  /* generate and fill the then block */
+  r = new_Block ();
+  add_in_edge (r, t);
+  // mature_block (r);
+  a = new_Sub(get_value(a_pos, mode_i),
+              new_Const (mode_i, tarval_from_long (mode_i, 2)),
+             mode_i);
+  set_value (a_pos, a);
+
+  mature_block (r);
+  x = new_Jmp ();
+
+  /* generate the fall through block and add all cfg edges */
+  r = new_Block ();
+  add_in_edge (r, f);
+  add_in_edge (r, x);
+  mature_block (r);
+  {
+     ir_node *in[3], *store ;
+     in[0] = get_value (a_pos, mode_i);
+     in[1] = a;
+     in[2] = get_value (b_pos, mode_i);
+     store = get_store();
+
+     x = new_Return (store, 2, in);
+  }
+
+  /* finalize the end block generated in new_ir_graph() */
+  add_in_edge (irg->end_block, x);
+  mature_block (irg->end_block);
+
+  /* output the vcg file */
+  printf("\nDone building the graph.  Dumping it.\n");
+
+  dump_ir_block_graph (irg);
+
+  printf("use xvcg to view this graph:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+}
diff --git a/testprograms/if_while_example.c b/testprograms/if_while_example.c
new file mode 100644 (file)
index 0000000..75b6eb2
--- /dev/null
@@ -0,0 +1,122 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+# include "irdump.h"
+# include "firm.h"
+
+/**
+***  This file constructs the ir for the following pseudo-program:
+***
+***  main() {
+***    int a = 0;
+***    int b = 1;
+***
+***    if (0 == 0)
+***      { a = 2; }
+***
+***    while (0 == 0) loop {
+***      h = a;
+***      a = b;
+***      b = h;
+***    }
+***
+***    return a-b;
+**/
+
+int
+main(void)
+{
+  ir_graph *irg;
+  type_class *owner;
+  entity *ent;
+  ir_node *b, *x, *r, *t, *f;
+
+  printf("creating an IR graph: IF_WHILE_EXAMPLE...\n");
+
+  init_firm ();
+
+  owner = new_type_class (id_from_str ("IF_WHILE_EXAMPLE", 16));
+  ent = new_entity ((type *)owner, id_from_str ("main", 4), NULL);
+
+  /* Generates start and end blocks and nodes and a first, initial block */
+  irg = new_ir_graph (ent, 4);
+
+  /* Generate two constants */
+  set_value (0, new_Const (mode_I, tarval_from_long (mode_i, 0)));
+  set_value (1, new_Const (mode_I, tarval_from_long (mode_i, 1)));
+  mature_block (irg->current_block);
+
+  /* Generate a conditional branch */
+  x = new_Cond (new_Proj(new_Cmp(new_Const (mode_I, tarval_from_long (mode_i, 0)),
+                                 new_Const (mode_I, tarval_from_long (mode_i, 0))),
+                         mode_b, Eq));
+  f = new_Proj (x, mode_X, 0);
+  t = new_Proj (x, mode_X, 1);
+
+  /* generate and fill the then block */
+  r = new_Block ();
+  add_in_edge (r, t);
+  set_value (0, new_Const (mode_I, tarval_from_long (mode_i, 2)));
+  mature_block (r);
+  x = new_Jmp ();
+
+  /* generate the fall through block and add all cfg edges */
+  r = new_Block ();
+  add_in_edge (r, f);
+  add_in_edge (r, x);
+  mature_block (r);
+  x = new_Jmp ();
+
+  /* generate a block for the loop header and the conditional branch */
+  r = new_Block ();
+  add_in_edge (r, x);
+  x = new_Cond (new_Proj(new_Cmp(new_Const (mode_I, tarval_from_long (mode_i, 0)),
+                                 new_Const (mode_I, tarval_from_long (mode_i, 0))),
+                         mode_b, Eq));
+  f = new_Proj (x, mode_X, 0);
+  t = new_Proj (x, mode_X, 1);
+
+  /* generate the block for the loop body */
+  b = new_Block ();
+  add_in_edge (b,t);
+  x = new_Jmp ();
+  add_in_edge (r, x);
+  mature_block (r);
+
+  /* the code in the loop body,
+     as we are dealing with local variable only the dataflow edges are manipulated */
+  set_value (2, get_value (0, mode_I));
+  set_value (0, get_value (1, mode_I));
+  set_value (1, get_value (2, mode_I));
+  mature_block (b);
+
+  /* generate the return block */
+  r = new_Block ();
+  add_in_edge (r, f);
+  mature_block (r);
+
+  {
+     ir_node *in[1];
+     in[0] = new_Sub (get_value (0, mode_I), get_value (1, mode_I), mode_I);
+
+     x = new_Return (get_store (), 1, in);
+  }
+
+  /* finalize the end block generated in new_ir_graph() */
+  add_in_edge (irg->end_block, x);
+  mature_block (irg->end_block);
+
+  /* output the vcg file */
+  printf("\nDone building the graph.  Dumping it.\n");
+  dump_ir_block_graph (irg);
+
+  printf("use xvcg to view this graph:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+}
diff --git a/testprograms/irr_cf_example.c b/testprograms/irr_cf_example.c
new file mode 100644 (file)
index 0000000..d461668
--- /dev/null
@@ -0,0 +1,135 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+#include <stdio.h>
+
+# include "irdump.h"
+# include "firm.h"
+
+/*
+ *  irregular control flow
+ */
+
+/**
+***  This file constructs a control flow of following shape:
+***
+*** StartBlock
+***     |
+***    \|/
+***   Block --->  Block
+***     |           |
+***    \|/         \|/
+***   Block --->  Block
+***     |           |
+***    \|/         \|/
+***   Block --->  Block
+***                 |
+***                \|/
+***              EndBlock
+***
+***   This is a program as, e.g.,
+***
+***   switch (expr){
+***     case 1:
+***     case 2:
+***       break;
+***     default:
+***   }
+***   return
+**/
+
+int main(int argc, char **argv)
+{
+  ir_graph *irg;          /* this variable contains the irgraph */
+  type_class *owner;      /* the class in which this method is defined */
+  type_method *proc_main; /* typeinformation for the method main */
+  entity *ent;            /* represents this method as entity of owner */
+  ir_node *expr, *c1, *c2, *cond, *f, *t, *jmp, *x;
+
+  printf("creating an IR graph: IRR_CF...\n");
+
+  /* init library */
+  init_firm ();
+
+  /* FIRM was designed for oo languages where all methods belong to a class.
+   * For imperative languages like C we view a file as a large class containing
+   * all functions as methods in this file.
+   * Therefore we define a class "empty" according to the file name
+   * with a method main as an entity.
+   */
+#define CLASSNAME "IRREGULAR_CF"
+#define METHODNAME "main"
+#define NRARGS 0
+#define NRES 0
+
+  owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
+  proc_main = new_type_method(id_from_str(METHODNAME, strlen(METHODNAME)),
+                              NRARGS, NRES);
+  ent = new_entity ((type *)owner,
+                    id_from_str (METHODNAME, strlen(METHODNAME)),
+                    (type *)proc_main);
+
+#define NUM_OF_LOCAL_VARS 0
+
+  irg = new_ir_graph (ent, NUM_OF_LOCAL_VARS);
+
+  /* two make two conditionals that represent a switch */
+  expr = new_Const (mode_i, tarval_from_long (mode_i, 0));
+  c1 = new_Const (mode_i, tarval_from_long (mode_i, 1));
+  c2 = new_Const (mode_i, tarval_from_long (mode_i, 2));
+
+  cond = new_Cond(new_Proj(new_Cmp(expr, c1), mode_b, Eq));
+  f = new_Proj(cond, mode_X, 0);
+  t = new_Proj(cond, mode_X, 1);
+  mature_block(irg->current_block);
+
+  new_Block();
+  add_in_edge(irg->current_block, t);
+  jmp = new_Jmp();
+  mature_block(irg->current_block);
+
+  new_Block();
+  add_in_edge(irg->current_block, f);
+  cond = new_Cond(new_Proj(new_Cmp(expr, c2), mode_b, Eq));
+  f = new_Proj(cond, mode_X, 0);
+  t = new_Proj(cond, mode_X, 1);
+  mature_block(irg->current_block);
+
+  new_Block();
+  add_in_edge(irg->current_block, t);
+  add_in_edge(irg->current_block, jmp);
+  jmp = new_Jmp();
+  mature_block(irg->current_block);
+
+  new_Block();
+  add_in_edge(irg->current_block, f);
+  t = new_Jmp();
+  mature_block(irg->current_block);
+
+  new_Block();
+  add_in_edge(irg->current_block, t);
+  add_in_edge(irg->current_block, jmp);
+  {
+    ir_node *in[0]; /* this is the array containing the return parameters */
+    x = new_Return (get_store(), 0, in);
+  }
+  mature_block (irg->current_block);
+
+  add_in_edge (irg->end_block, x);
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph.\n");
+  printf("Dumping the graph and a control flow graph.\n");
+  dump_ir_block_graph (irg);
+  dump_cfg (irg);
+
+  printf("use xvcg to view these graphs:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+}
diff --git a/testprograms/irr_loop_example.c b/testprograms/irr_loop_example.c
new file mode 100644 (file)
index 0000000..b567cc9
--- /dev/null
@@ -0,0 +1,123 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+# include <stdio.h>
+
+# include "irdump.h"
+# include "firm.h"
+
+/*
+ *   an irreducible loop.
+ */
+
+/**
+***  This file constructs a control flow of following shape:
+***
+***
+***         firstBlock
+***          /      \
+***         /        \
+***       |/_        _\|
+***            ---->
+*** LoopBlock1       LoopBlock2
+***            <----
+***        \              /
+***        \            /
+***        _\|        |/_
+***           nextBlock
+***
+***
+**/
+
+int main(int argc, char **argv)
+{
+  ir_graph *irg;          /* this variable contains the irgraph */
+  type_class *owner;      /* the class in which this method is defined */
+  type_method *proc_main; /* typeinformation for the method main */
+  entity *ent;            /* represents this method as entity of owner */
+  ir_node *expr, *c1, *c2, *c3, *cond, *f, *t, *loopBlock1, *f_l1, *t_l1,
+          *loopBlock2, *f_l2, *t_l2, *x;
+
+
+  /* init library */
+  init_firm ();
+  set_opt_constant_folding (1);
+
+  /* FIRM was designed for oo languages where all methods belong to a class.
+   * For imperative languages like C we view a file as a large class containing
+   * all functions as methods in this file.
+   * Therefore we define a class "empty" according to the file name
+   * with a method main as an entity.
+   */
+#define CLASSNAME "IRR_LOOP"
+#define METHODNAME "main"
+#define NRARGS 0
+#define NRES 0
+  printf("creating an IR graph: %s...\n", CLASSNAME);
+
+  owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
+  proc_main = new_type_method(id_from_str(METHODNAME, strlen(METHODNAME)),
+                              NRARGS, NRES);
+  ent = new_entity ((type *)owner,
+                    id_from_str (METHODNAME, strlen(METHODNAME)),
+                    (type *)proc_main);
+
+#define NUM_OF_LOCAL_VARS 0
+
+  irg = new_ir_graph (ent, NUM_OF_LOCAL_VARS);
+
+  /* two make three conditionals  */
+  expr = new_Const (mode_i, tarval_from_long (mode_i, 0));
+  c1 = new_Const (mode_i, tarval_from_long (mode_i, 1));
+  c2 = new_Const (mode_i, tarval_from_long (mode_i, 2));
+  c3 = new_Const (mode_i, tarval_from_long (mode_i, 2));
+
+  cond = new_Cond(new_Proj(new_Cmp(expr, c1), mode_b, Eq));
+  f = new_Proj(cond, mode_X, 0);
+  t = new_Proj(cond, mode_X, 1);
+  mature_block(irg->current_block);
+
+  loopBlock1 = new_Block();
+  add_in_edge(loopBlock1, t);
+  cond = new_Cond(new_Proj(new_Cmp(expr, c2), mode_b, Eq));
+  f_l1 = new_Proj(cond, mode_X, 0);
+  t_l1 = new_Proj(cond, mode_X, 1);
+
+  loopBlock2 = new_Block();
+  add_in_edge(loopBlock2, f);
+  cond = new_Cond(new_Proj(new_Cmp(expr, c3), mode_b, Eq));
+  f_l2 = new_Proj(cond, mode_X, 0);
+  t_l2 = new_Proj(cond, mode_X, 1);
+
+  add_in_edge(loopBlock1, t_l2);
+  add_in_edge(loopBlock2, t_l1);
+  mature_block(loopBlock1);
+  mature_block(loopBlock2);
+
+  new_Block();
+  add_in_edge(irg->current_block, f_l2);
+  add_in_edge(irg->current_block, f_l1);
+  {
+    ir_node *in[0];
+    x = new_Return (get_store(), 1, in);
+  }
+  mature_block (irg->current_block);
+
+  add_in_edge (irg->end_block, x);
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph..\n");
+  printf("Dumping the graph and a control flow graph.\n");
+  dump_ir_block_graph (irg);
+  dump_cfg (irg);
+
+  printf("use xvcg to view these graphs:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+}
diff --git a/testprograms/memory_example.c b/testprograms/memory_example.c
new file mode 100644 (file)
index 0000000..4b0c850
--- /dev/null
@@ -0,0 +1,141 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Christian Schaefer, Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+# include "irdump.h"
+# include "firm.h"
+
+/**  This example demonstrates the use of memory edges.
+***  This file constructs the ir for the following pseudo-program:
+***
+***  int VAR_A
+***  int VAR_B
+***
+***  main() {
+***
+***    VAR_A = 0
+***    VAR_B = 1
+***
+***    repeat {
+***      h = VAR_A;
+***      VAR_A = VAR_B;
+***      VAR_B = h;
+***    } until (0 == h)
+***
+***    return (VAR_A)
+***  }
+***
+***
+***  A better example would be the following program:
+***  (name e.g.: memory-imp_example.c as it models imperative concepts.)
+***
+***  In this program a local variable is dereferenced.  It has
+***  to be modeled as an entity of the stack so that a pointer to it is available.
+***  It is also an example where an analysis could find out that the
+***  pointer is never actually used.
+***
+***  main () {
+***    int a;
+***    int *p;
+***
+***    a = 2;
+***    p = &a;
+***    return (*p);
+***  }
+***
+**/
+
+int
+main(void)
+{
+  ir_graph *irg;
+  type_class *owner;
+  entity *ent;
+  ir_node *a, *b, *x, *y, *r;
+
+  printf("creating an IR graph: MEMORY_EXAMPLE...\n");
+
+  init_firm ();
+
+  /* a class to get started with, containing the main procedure */
+  owner = new_type_class (id_from_str ("MEMORY_EXAMPLE", 14));
+  ent = new_entity ((type *)owner, id_from_str ("main", 4), NULL);
+
+  /* Generates start and end blocks and nodes and a first, initial block */
+  irg = new_ir_graph (ent, 4);
+
+  /* generate two constant pointers to string constants */
+  /* this simulates two global variables, a and b point to these variables */
+  a = new_Const (mode_p, tarval_p_from_str ("VAR_A"));
+  b = new_Const (mode_p, tarval_p_from_str ("VAR_B"));
+
+  /* set VAR_A and VAR_B to constant values */
+  set_store (new_Proj (new_Store (get_store (), a,
+                                 new_Const (mode_I, tarval_from_long (mode_i, 0))),
+                       mode_M, 0));
+
+  set_store (new_Proj (new_Store (get_store (), b,
+                                 new_Const (mode_I, tarval_from_long (mode_i, 1))),
+                       mode_M, 0));
+
+  /* finish this first block */
+  x = new_Jmp ();
+  mature_block (irg->current_block);
+
+  /* a loop body */
+  r = new_Block ();
+  add_in_edge (r, x);
+
+  /* exchange the content of the two variables. Exceptions not cached. */
+  /* load the value and make it's effects visible. */
+  x = new_Load (get_store (), a);
+    set_store (new_Proj (x, mode_M, 0));
+    x = new_Proj(x, mode_I, 2);
+  /* the same again: load the value and make it's effects visible. */
+  y = new_Load (get_store (), b);
+    set_store (new_Proj (y, mode_M, 0));
+    y = new_Proj(y, mode_I, 2);
+  /* store the exchanged values. */
+  set_store (new_Proj (new_Store (get_store (), a, y), mode_M, 0));
+  set_store (new_Proj (new_Store (get_store (), b, x), mode_M, 0));
+
+  /* test the condition */
+  x = new_Cond (
+        new_Proj (
+          new_Cmp (
+            new_Const (mode_I, tarval_from_long (mode_i, 0)),
+            x),
+          mode_b, Gt));
+  /* build the cfg of the loop */
+  add_in_edge (r, new_Proj (x, mode_X, 0));
+  x = new_Proj (x, mode_X, 1);
+  mature_block(r);
+
+  /* generate the block the loop exits to */
+  r = new_Block ();
+  add_in_edge (r, x);
+
+  /* generate the return block and return the content of VAR_A */
+  {
+     ir_node *in[1];
+     x = new_Load (get_store (), a);
+     in[0] = new_Proj (x, mode_I, 2);
+
+     x = new_Return (new_Proj(x, mode_M, 0), 1, in);
+  }
+  mature_block (r);
+  add_in_edge (irg->end_block, x);
+  mature_block (irg->end_block);
+
+  printf("\nDone building the graph.  Dumping it.\n");
+  dump_ir_block_graph (irg);
+
+  printf("use xvcg to view this graph:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (0);
+}
diff --git a/testprograms/oo_program_example.c b/testprograms/oo_program_example.c
new file mode 100644 (file)
index 0000000..28e7b5d
--- /dev/null
@@ -0,0 +1,214 @@
+/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
+** All rights reserved.
+**
+** Authors: Goetz Lindenmaier
+**
+** testprogram.
+*/
+
+# include "irdump.h"
+# include "firm.h"
+
+/**  This file constructs the IR for the following program:
+***
+***  class PRIMA
+***    a: int;
+***    b: real;
+***    c(int): int;
+***    set_a(int): void;
+***  end
+***
+***  c(d: int): int
+***    return (d + a);
+***  end
+***
+***  set_a(e:int):void
+***    self.a = e;
+***  end
+***
+***  main(): int
+***    o: PRIMA;
+***    o.set_a(2);
+***    return o.c(5);
+***  end
+***
+**/
+
+#define OPTIMIZE_NODE 0
+
+int
+main(void)
+{
+  type_primitive *prim_t_int;
+  type_class   *owner, *class_prima, *class_langint;
+  type_method  *proc_main, *proc_set, *proc_c;
+  type_pointer *class_p_ptr;
+  entity       *proc_main_e, *proc_set_e, *proc_c_e, *a_e;
+
+  ir_graph     *main_irg, *set_a_irg, *c_irg;
+  ir_node      *c2, *c5, *obj_o, *obj_size, *proc_ptr, *call, *x;
+  ir_node      *self, *par1, *a_ptr;
+  ir_node      *a_val;
+
+  init_firm ();
+
+  set_opt_constant_folding(0);
+  set_opt_cse(0);
+
+  /* make basic type information for primitive type int.*/
+  prim_t_int = new_type_primitive(id_from_str ("int", 3), mode_i);
+
+  /* first build procedure main */
+  printf("creating an IR graph: OO_PROGRAM_EXAMPLE...\n");
+  owner = new_type_class (id_from_str ("OO_PROGRAM_EXAMPLE", 18));
+  proc_main = new_type_method(id_from_str("main", 4), 0, 1);
+  set_method_res_type(proc_main, 0, (type *)prim_t_int);
+
+  proc_main_e = new_entity ((type *)owner, id_from_str ("main", 4),
+                            (type *)proc_main);
+  main_irg = new_ir_graph (proc_main_e, 4);
+
+  /* There is only one block in main, it contains the constants and the calls. */
+  c2 = new_Const (mode_i, tarval_from_long (mode_i, 2));
+  c5 = new_Const (mode_i, tarval_from_long (mode_i, 5));
+
+  /* allocate the defined object and generate the type information */
+  class_prima = new_type_class(id_from_str ("PRIMA", 5));
+  obj_size = new_SymConst((type *)class_prima, size);
+  obj_o    = new_Alloc(get_store(), obj_size, (type *)class_prima, heap_alloc);
+  set_store(new_Proj(obj_o, mode_M, 0));  /* make the changed memory visible */
+  obj_o    = new_Proj(obj_o, mode_p, 1);  /* remember the pointer to the object */
+  /* we need type information for pointers to the class: */
+  class_p_ptr = new_type_pointer (id_from_str ("class_prima_ptr", 15),
+                                 (type *)class_prima);
+
+  /* get the pointer to the procedure from the class type */
+  proc_set = new_type_method(id_from_str("set_a", 5), 2, 0);
+  set_method_param_type(proc_set, 0, (type *)class_p_ptr);
+  set_method_param_type(proc_set, 1, (type *)prim_t_int);
+  proc_set_e = new_entity((type *)class_prima, id_from_str ("set_a", 5),
+                         (type*)proc_set);
+  proc_ptr = new_simpleSel(get_store(),  /* The memory the object is allocated in */
+                     obj_o,             /* The pointer to the object */
+                     proc_set_e );      /* The feature to select */
+
+  /* call procedure set_a, first built array with parameters */
+  {
+    ir_node *in[2];
+    in[0] = obj_o;
+    in[1] = c2;
+    call = new_Call(get_store(), proc_ptr, 2, in, proc_set);
+  }
+  /* make the change to memory visible */
+  set_store(new_Proj(call, mode_M, 0));
+
+  /* get the pointer to the procedure from the class type */
+  proc_c   = new_type_method(id_from_str("c", 1 ), 2, 1);
+  set_method_param_type(proc_c, 0, (type *)class_p_ptr);
+  set_method_param_type(proc_c, 1, (type *)prim_t_int);
+  set_method_res_type(proc_c, 0, (type *)prim_t_int);
+  proc_c_e = new_entity((type *)class_prima, id_from_str ("c", 1),
+                       (type*)proc_c);
+  proc_ptr = new_simpleSel(get_store(), obj_o, proc_c_e);
+
+  /* call procedure c, first built array with parameters */
+  {
+    ir_node *in[2];
+    in[0] = obj_o;
+    in[1] = c5;
+    call = new_Call(get_store(), proc_ptr, 2, in, proc_c);
+  }
+  /* make the change to memory visible */
+  set_store(new_Proj(call, mode_M, 0));
+
+  /* return the results of procedure main */
+  {
+     ir_node *in[1];
+     /* Select the result tuple from the call, then the proper
+        result from the tuple. */
+     in[0] = new_Proj(new_Proj(call, mode_T, 1), mode_I, 0);
+
+     x = new_Return (get_store (), 1, in);
+  }
+  mature_block (main_irg->current_block);
+
+  /* complete the end_block */
+  add_in_edge (main_irg->end_block, x);
+  mature_block (main_irg->end_block);
+
+  printf("\nDone building the graph.\n");
+  printf("Dumping the graph and a type graph.\n");
+  dump_ir_block_graph (main_irg);
+  dump_type_graph(main_irg);
+
+  /****************************************************************************/
+
+  printf("\ncreating IR graph for set_a: \n");
+
+  set_a_irg = new_ir_graph (proc_set_e, 4);
+
+  /* get the procedure parameter */
+  self = new_Proj(set_a_irg->args, mode_p, 0);
+  par1 = new_Proj(set_a_irg->args, mode_I, 1);
+  /* Create and select the entity to set */
+  class_langint = new_type_class(id_from_str ("Int", 3));
+  a_e = new_entity((type *)class_prima, id_from_str ("a", 1),
+                  (type*)class_langint);
+  a_ptr = new_simpleSel(get_store(), self, a_e);
+  /* perform the assignment */
+  set_store(new_Proj(new_Store(get_store(), a_ptr, par1), mode_M, 0));
+
+  /* return nothing */
+  x = new_Return (get_store (), 0, NULL);
+  mature_block (set_a_irg->current_block);
+
+  /* complete the end_block */
+  add_in_edge (set_a_irg->end_block, x);
+  mature_block (set_a_irg->end_block);
+
+  printf("\nDone building the graph.\n");
+  printf("Dumping the graph and a type graph.\n");
+  dump_ir_block_graph (set_a_irg);
+  dump_type_graph(set_a_irg);
+
+  /****************************************************************************/
+
+  printf("\ncreating IR graph for c: \n");
+
+  c_irg = new_ir_graph (proc_c_e, 4);
+
+  /* get the procedure parameter */
+  self = new_Proj(c_irg->args, mode_p, 0);
+  par1 = new_Proj(c_irg->args, mode_I, 1);
+
+  /* Select the entity and load the value */
+  a_ptr = new_simpleSel(get_store(), self, a_e);
+  a_val = new_Load(get_store(), a_ptr);
+  set_store(new_Proj(a_val, mode_M, 0));
+  a_val = new_Proj(a_val, mode_I, 1);
+
+  /* return the result */
+  {
+    ir_node *in[1];
+    in[0] = new_Add(par1, a_val, mode_I);
+
+    x = new_Return (get_store (), 1, in);
+  }
+  mature_block (c_irg->current_block);
+
+  /* complete the end_block */
+  add_in_edge (c_irg->end_block, x);
+  mature_block (c_irg->end_block);
+
+  printf("\nDone building the graph.\n");
+  printf("Dumping the graph and a type graph.\n");
+  dump_ir_block_graph (c_irg);
+  dump_type_graph(c_irg);
+
+  /****************************************************************************/
+
+  printf("\nuse xvcg to view these graphs:\n");
+  printf("/ben/trapp/bin/i486/xvcg GRAPHNAME\n");
+
+  return (1);
+}