# $Header$
EMHOME=../..
-CFILES=main.c getline.c lookup.c var.c process.c backward.c util.c\
- alloc.c putline.c cleanup.c peephole.c flow.c reg.c
+CFILES=main.c getline.c lookup.c var.c process.c backward.c util.c \
+ alloc.c putline.c cleanup.c peephole.c flow.c reg.c shc.c \
+ pop_push.c
+
OFILES=main.o getline.o lookup.o var.o process.o backward.o util.o\
- alloc.o putline.o cleanup.o peephole.o flow.o
+ alloc.o putline.o cleanup.o peephole.o flow.o shc.o pop_push.o
ONOGLOB=regnoglob.o
OGLOB=regglob.o
LIBS=$(EMHOME)/lib/em_data.a
all: opt opt2
-opt: $(OFILES) $(ONOGLOB) pattern.o $(LIBS)
+opt: $(OFILES) $(ONOGLOB) pattern.o $(LIBS)
$(CC) $(LDFLAGS) $(CFLAGS) $(OFILES) $(ONOGLOB) pattern.o $(LIBS) -o opt
-opt2: $(OFILES) $(OGLOB) pattern.o $(LIBS)
+opt2: $(OFILES) $(OGLOB) pattern.o $(LIBS)
$(CC) $(LDFLAGS) $(CFLAGS) $(OFILES) $(OGLOB) pattern.o $(LIBS) -o opt2
-test: opt testopt
+test: opt testopt
testopt
-cmp : all
+cmp: all
-cmp opt $(EMHOME)/lib/em_opt
-cmp opt2 $(EMHOME)/lib/em_opt2
-cmp em_opt.6 $(EMHOME)/man/em_opt.6
rm -f $(EMHOME)/man/em_opt.6
cp em_opt.6 $(EMHOME)/man/em_opt.6
-pattern.c: patterns mktab
+pattern.c: patterns mktab
$(CPP) patterns | mktab > pattern.c
-mktab: mktab.o $(LIBS)
+mktab: mktab.o $(LIBS)
$(CC) $(CFLAGS) mktab.o $(LIBS) $(LEXLIB) -o mktab
mktab.o: scan.c optim.h param.h pattern.h types.h
+pop_push.c ./pop_push.h: $(EMHOME)/etc/em_table pop_push.awk
+ awk -f pop_push.awk < $(EMHOME)/etc/em_table > pop_push.c
+
depend: pattern.c
sed '/^#AUTOAUTO/,$$d' Makefile >Makefile.new
echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >> Makefile.new
mv Makefile Makefile.old
mv Makefile.new Makefile
-lint: $(CFILES) pattern.c
- $(LINT) $(CFILES) pattern.c>lint 2>&1
+lint: $(CFILES) pattern.c
+ $(LINT) $(CFLAGS) $(CFILES) pattern.c>lint 2>&1
printall:
-pr $(PROPTS) Makefile -n *.h `ls $(CFILES)` mktab.y scan.l patterns|$(OPR)
touch print
-print: Makefile *.h $(CFILES) mktab.y scan.l patterns
+print: Makefile *.h $(CFILES) mktab.y scan.l patterns
-pr $(PROPTS) -n $? | $(OPR)
touch print
@pr $(PROPTS) -n Makefile *.h $(CFILES) mktab.y scan.l patterns
clean:
- rm -f *.o opt mktab mktab.c scan.c pattern.c opt2 Out
+ rm -f *.o opt mktab mktab.c scan.c pattern.c opt2 Out \
+ pop_push.c pop_push.h
regnoglob.o: reg.c
$(CC) $(CFLAGS) -c -o regnoglob.o reg.c
main.o: alloc.h
main.o: ext.h
main.o: param.h
+main.o: shc.h
main.o: types.h
getline.o: alloc.h
getline.o: ext.h
getline.o: lookup.h
getline.o: param.h
getline.o: proinf.h
+getline.o: shc.h
getline.o: types.h
lookup.o: alloc.h
lookup.o: lookup.h
lookup.o: param.h
lookup.o: proinf.h
+lookup.o: shc.h
lookup.o: types.h
var.o: lookup.h
var.o: param.h
var.o: proinf.h
+var.o: shc.h
var.o: types.h
process.o: alloc.h
process.o: assert.h
process.o: lookup.h
process.o: param.h
process.o: proinf.h
+process.o: shc.h
process.o: types.h
backward.o: alloc.h
backward.o: assert.h
backward.o: lookup.h
backward.o: param.h
backward.o: proinf.h
+backward.o: shc.h
backward.o: types.h
util.o: assert.h
util.o: ext.h
util.o: optim.h
util.o: param.h
util.o: proinf.h
+util.o: shc.h
util.o: types.h
alloc.o: alloc.h
alloc.o: assert.h
alloc.o: lookup.h
alloc.o: param.h
alloc.o: proinf.h
+alloc.o: shc.h
alloc.o: types.h
putline.o: alloc.h
putline.o: assert.h
putline.o: optim.h
putline.o: param.h
putline.o: proinf.h
+putline.o: shc.h
putline.o: types.h
cleanup.o: assert.h
cleanup.o: ext.h
peephole.o: param.h
peephole.o: pattern.h
peephole.o: proinf.h
+peephole.o: shc.h
peephole.o: types.h
flow.o: alloc.h
flow.o: ext.h
flow.o: optim.h
flow.o: param.h
flow.o: proinf.h
+flow.o: shc.h
flow.o: types.h
reg.o: alloc.h
reg.o: assert.h
reg.o: line.h
reg.o: param.h
reg.o: proinf.h
+reg.o: shc.h
reg.o: types.h
+shc.o: alloc.h
+shc.o: assert.h
+shc.o: ext.h
+shc.o: line.h
+shc.o: param.h
+shc.o: pop_push.h
+shc.o: proinf.h
+shc.o: shc.h
+shc.o: types.h
+pop_push.o: pop_push.h
pattern.o: param.h
pattern.o: pattern.h
pattern.o: types.h
regglob.o: line.h
regglob.o: param.h
regglob.o: proinf.h
+regglob.o: shc.h
regglob.o: types.h
regnoglob.o: alloc.h
regnoglob.o: assert.h
regnoglob.o: line.h
regnoglob.o: param.h
regnoglob.o: proinf.h
+regnoglob.o: shc.h
regnoglob.o: types.h
--- /dev/null
+/*
+ * This file contains the main part of the stackheight computation phase.
+ *
+ * Author: Hans van Eck.
+ */
+
+#include <stdio.h>
+#include <em_spec.h>
+#include <em_mnem.h>
+#include <em_pseu.h>
+#include "param.h"
+#include "assert.h"
+#include "types.h"
+#include "shc.h"
+#include "alloc.h"
+#include "proinf.h"
+#include "line.h"
+#include "ext.h"
+#include "pop_push.h"
+
+extern char *pop_push[];
+extern char flow_tab[];
+
+#define NON_CONTINUABLE(i) (flow_tab[i]&JUMP)
+#define ISABRANCH(i) (flow_tab[i]&HASLABEL)
+#define ISCONDBRANCH(i) (flow_tab[i]&CONDBRA)
+
+lblst_p est_list = NULL;
+
+#define INSTR(lnp) (lnp->l_instr & BMASK)
+#define TYPE(lnp) lnp->l_optyp
+#define PREV(lnp) lnp->l_prev
+#define SHORT(lnp) lnp->l_a.la_short
+#define MINI(lnp) ((lnp->l_optyp & BMASK) - Z_OPMINI)
+
+#define IS_MINI(lnp) (lnp->l_optyp >= OPMINI)
+#define IS_LOC(l) (l!=(line_p) 0 && INSTR(l)==op_loc && IS_MINI(l))
+
+int state;
+static int stack_height = 0;
+
+init_state()
+{
+ stack_height = 0;
+ change_state(KNOWN);
+ est_list = NULL;
+}
+
+shc_pseudos()
+{
+ register line_p lp;
+
+ for (lp = pseudos; lp != (line_p)0; lp = lp->l_next) {
+ switch(INSTR(lp)) {
+ case ps_con:
+ case ps_rom:
+ if (lp->l_optyp == OPLIST) {
+ register arg_p ap = lp->l_a.la_arg;
+
+ while (ap != (arg_p) 0) {
+ if (ap->a_typ == ARGNUM) {
+ assign_label(ap->a_a.a_np->n_repl);
+ }
+ ap = ap->a_next;
+ }
+ } else if (lp->l_optyp == OPNUMLAB)
+ assign_label(lp->l_a.la_np->n_repl);
+ }
+ }
+}
+
+shc_instr(lnp)
+line_p lnp;
+{
+ char *s;
+ register instr = INSTR(lnp);
+ register int mult, arg, argdef;
+ line_p x = PREV(lnp);
+ line_p y = (x == (line_p) 0 ? (line_p) 0 : PREV(x));
+
+ if (state == NO_STACK_MES) return;
+
+ if ( instr == op_lab) {
+ do_inst_label(lnp);
+ return;
+ }
+ if (instr < sp_fmnem || instr > sp_lmnem) {
+ return;
+ }
+
+ if(state == NOTREACHED) return; /* What else ? */
+ s = pop_push[instr];
+
+ if (*s != '0')
+ while (*s != '\0') {
+ if (*s++ == '-') mult = -1;
+ else mult = 1;
+ if (TYPE(lnp) == OPSHORT) {
+ arg = SHORT(lnp);
+ if (arg < wordsize) arg = wordsize;
+ argdef = TRUE;
+ } else if (IS_MINI(lnp)) {
+ arg = MINI(lnp);
+ if (arg > 0 && arg < wordsize) arg = wordsize;
+ if (arg < 0 && -arg < wordsize) arg = -wordsize;
+ argdef = TRUE;
+ } else argdef = FALSE;
+ switch (*s++) {
+ case 'w': stack_height += mult * wordsize; break;
+ case 'd': stack_height += mult * wordsize * 2; break;
+ case 'p': stack_height += mult * pointersize; break;
+ case 'a':
+ if (argdef == FALSE || instr == op_ass) {
+ change_state(NO_STACK_MES);
+ return;
+ }
+ stack_height += mult * arg;
+ break;
+ case 'x':
+ if (IS_LOC(x)) {
+ arg = MINI(x);
+ if (arg < wordsize) arg = wordsize;
+ stack_height += mult * arg;
+ break;
+ }
+ change_state(NO_STACK_MES);
+ return;
+ case 'y':
+ if (IS_LOC(y)) {
+ arg = MINI(y);
+ if (arg < wordsize) arg = wordsize;
+ stack_height += mult * arg;
+ break;
+ }
+ change_state(NO_STACK_MES);
+ return;
+ case '?':
+ /* Actually, the effect of a ret on the stack is
+ * known, but it has a '?' anyway. I think this
+ * should be changed in ~etc/em_table
+ */
+ if (instr == op_ret)
+ break;
+ change_state(NO_STACK_MES);
+ return;
+ default:
+ assert(FALSE);
+ }
+ }
+
+ if (ISABRANCH(instr)) do_inst_label(lnp);
+ if (NON_CONTINUABLE(instr)) change_state(NOTREACHED);
+}
+
+change_state(mode)
+int mode;
+{
+ state = mode;
+ if (mode != KNOWN) stack_height = 0;
+}
+
+delete_labels()
+{
+ register lblst_p tmp;
+
+ while ((tmp = est_list) != NULL) {
+ est_list = est_list->ll_next;
+ oldlblst(tmp);
+ }
+}
+
+inst_old_label(lst_elt)
+register lblst_p lst_elt;
+{
+ if (state != NOTREACHED) {
+ if (stack_height < 0 || lst_elt->ll_height != stack_height) {
+ change_state(NO_STACK_MES);
+ }
+ } else { /* after a label */
+ stack_height = lst_elt->ll_height;
+ change_state(KNOWN);
+ }
+}
+
+inst_new_label(label)
+register num_p label;
+{
+ register lblst_p lst_elt;
+
+ lst_elt = newlblst();
+ lst_elt->ll_next = est_list;
+ lst_elt->ll_num = label;
+ lst_elt->ll_height = stack_height;
+
+ est_list = lst_elt;
+
+ label->n_lst_elt = lst_elt;
+ label->n_flags |= NUMSET;
+}
+
+assign_label(label)
+num_p label;
+{
+ if (label->n_flags & NUMSET)
+ inst_old_label(label->n_lst_elt);
+ else inst_new_label(label);
+}
+
+do_inst_label(lnp) /* (re-)install a label */
+line_p lnp;
+{
+ num_p label = lnp->l_a.la_np->n_repl;
+ int instr = INSTR(lnp);
+
+ assign_label(label);
+
+ if (instr == op_lab) {
+ if (state == NOTREACHED) {
+ label->n_lst_elt->ll_fallthrough = FALSE;
+ } else {
+ label->n_lst_elt->ll_fallthrough = TRUE;
+ }
+ } else if (ISCONDBRANCH(instr)) { /* conditional branch */
+ label->n_flags |= NUMCOND;
+ }
+}