xref: /plan9/sys/src/cmd/spin/pangen5.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
17dd7cddfSDavid du Colombier /***** spin: pangen5.c *****/
27dd7cddfSDavid du Colombier 
3312a1df1SDavid du Colombier /* Copyright (c) 1999-2003 by Lucent Technologies, Bell Laboratories.     */
47dd7cddfSDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9312a1df1SDavid du Colombier /*             http://spinroot.com/                                       */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier #include "spin.h"
137dd7cddfSDavid du Colombier #include "y.tab.h"
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier typedef struct BuildStack {
167dd7cddfSDavid du Colombier 	FSM_trans *t;
177dd7cddfSDavid du Colombier 	struct BuildStack *nxt;
187dd7cddfSDavid du Colombier } BuildStack;
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier extern ProcList	*rdy;
21312a1df1SDavid du Colombier extern int verbose, eventmapnr, claimnr, rvopt, export_ast, u_sync;
227dd7cddfSDavid du Colombier extern Element *Al_El;
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier static FSM_state *fsm_free;
257dd7cddfSDavid du Colombier static FSM_trans *trans_free;
267dd7cddfSDavid du Colombier static BuildStack *bs, *bf;
277dd7cddfSDavid du Colombier static int max_st_id;
287dd7cddfSDavid du Colombier static int cur_st_id;
29312a1df1SDavid du Colombier int o_max;
30312a1df1SDavid du Colombier FSM_state *fsm;
31312a1df1SDavid du Colombier FSM_state **fsm_tbl;
32312a1df1SDavid du Colombier FSM_use   *use_free;
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier static void ana_seq(Sequence *);
357dd7cddfSDavid du Colombier static void ana_stmnt(FSM_trans *, Lextok *, int);
367dd7cddfSDavid du Colombier 
37312a1df1SDavid du Colombier extern void AST_slice(void);
38312a1df1SDavid du Colombier extern void AST_store(ProcList *, int);
39312a1df1SDavid du Colombier extern int  has_global(Lextok *);
40312a1df1SDavid du Colombier extern void exit(int);
41312a1df1SDavid du Colombier 
42312a1df1SDavid du Colombier static void
fsm_table(void)437dd7cddfSDavid du Colombier fsm_table(void)
447dd7cddfSDavid du Colombier {	FSM_state *f;
457dd7cddfSDavid du Colombier 	max_st_id += 2;
467dd7cddfSDavid du Colombier 	/* fprintf(stderr, "omax %d, max=%d\n", o_max, max_st_id); */
477dd7cddfSDavid du Colombier 	if (o_max < max_st_id)
487dd7cddfSDavid du Colombier 	{	o_max = max_st_id;
497dd7cddfSDavid du Colombier 		fsm_tbl = (FSM_state **) emalloc(max_st_id * sizeof(FSM_state *));
507dd7cddfSDavid du Colombier 	} else
517dd7cddfSDavid du Colombier 		memset((char *)fsm_tbl, 0, max_st_id * sizeof(FSM_state *));
527dd7cddfSDavid du Colombier 	cur_st_id = max_st_id;
537dd7cddfSDavid du Colombier 	max_st_id = 0;
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	for (f = fsm; f; f = f->nxt)
567dd7cddfSDavid du Colombier 		fsm_tbl[f->from] = f;
577dd7cddfSDavid du Colombier }
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier static int
FSM_DFS(int from,FSM_use * u)607dd7cddfSDavid du Colombier FSM_DFS(int from, FSM_use *u)
617dd7cddfSDavid du Colombier {	FSM_state *f;
627dd7cddfSDavid du Colombier 	FSM_trans *t;
637dd7cddfSDavid du Colombier 	FSM_use *v;
647dd7cddfSDavid du Colombier 	int n;
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier 	if (from == 0)
677dd7cddfSDavid du Colombier 		return 1;
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier 	f = fsm_tbl[from];
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier 	if (!f)
727dd7cddfSDavid du Colombier 	{	printf("cannot find state %d\n", from);
737dd7cddfSDavid du Colombier 		fatal("fsm_dfs: cannot happen\n", (char *) 0);
747dd7cddfSDavid du Colombier 	}
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier 	if (f->seen)
777dd7cddfSDavid du Colombier 		return 1;
787dd7cddfSDavid du Colombier 	f->seen = 1;
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)
817dd7cddfSDavid du Colombier 	{
827dd7cddfSDavid du Colombier 		for (n = 0; n < 2; n++)
837dd7cddfSDavid du Colombier 		for (v = t->Val[n]; v; v = v->nxt)
847dd7cddfSDavid du Colombier 			if (u->var == v->var)
857dd7cddfSDavid du Colombier 				return n;	/* a read or write */
867dd7cddfSDavid du Colombier 
877dd7cddfSDavid du Colombier 		if (!FSM_DFS(t->to, u))
887dd7cddfSDavid du Colombier 			return 0;
897dd7cddfSDavid du Colombier 	}
907dd7cddfSDavid du Colombier 	return 1;
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier 
937dd7cddfSDavid du Colombier static void
new_dfs(void)947dd7cddfSDavid du Colombier new_dfs(void)
957dd7cddfSDavid du Colombier {	int i;
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier 	for (i = 0; i < cur_st_id; i++)
987dd7cddfSDavid du Colombier 		if (fsm_tbl[i])
997dd7cddfSDavid du Colombier 			fsm_tbl[i]->seen = 0;
1007dd7cddfSDavid du Colombier }
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier static int
good_dead(Element * e,FSM_use * u)1037dd7cddfSDavid du Colombier good_dead(Element *e, FSM_use *u)
1047dd7cddfSDavid du Colombier {
1057dd7cddfSDavid du Colombier 	switch (u->special) {
1067dd7cddfSDavid du Colombier 	case 2:	/* ok if it's a receive */
1077dd7cddfSDavid du Colombier 		if (e->n->ntyp == ASGN
1087dd7cddfSDavid du Colombier 		&&  e->n->rgt->ntyp == CONST
1097dd7cddfSDavid du Colombier 		&&  e->n->rgt->val == 0)
1107dd7cddfSDavid du Colombier 			return 0;
1117dd7cddfSDavid du Colombier 		break;
1127dd7cddfSDavid du Colombier 	case 1:	/* must be able to use oval */
1137dd7cddfSDavid du Colombier 		if (e->n->ntyp != 'c'
1147dd7cddfSDavid du Colombier 		&&  e->n->ntyp != 'r')
1157dd7cddfSDavid du Colombier 			return 0;	/* can't really happen */
1167dd7cddfSDavid du Colombier 		break;
1177dd7cddfSDavid du Colombier 	}
1187dd7cddfSDavid du Colombier 	return 1;
1197dd7cddfSDavid du Colombier }
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier #if 0
1227dd7cddfSDavid du Colombier static int howdeep = 0;
123312a1df1SDavid du Colombier #endif
1247dd7cddfSDavid du Colombier 
1257dd7cddfSDavid du Colombier static int
eligible(FSM_trans * v)1267dd7cddfSDavid du Colombier eligible(FSM_trans *v)
1277dd7cddfSDavid du Colombier {	Element	*el = ZE;
1287dd7cddfSDavid du Colombier 	Lextok	*lt = ZN;
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier 	if (v) el = v->step;
1317dd7cddfSDavid du Colombier 	if (el) lt = v->step->n;
1327dd7cddfSDavid du Colombier 
1337dd7cddfSDavid du Colombier 	if (!lt				/* dead end */
1347dd7cddfSDavid du Colombier 	||  v->nxt			/* has alternatives */
1357dd7cddfSDavid du Colombier 	||  el->esc			/* has an escape */
1367dd7cddfSDavid du Colombier 	||  (el->status&CHECK2)		/* remotely referenced */
1377dd7cddfSDavid du Colombier 	||  lt->ntyp == ATOMIC
1387dd7cddfSDavid du Colombier 	||  lt->ntyp == NON_ATOMIC	/* used for inlines -- should be able to handle this */
1397dd7cddfSDavid du Colombier 	||  lt->ntyp == IF
140312a1df1SDavid du Colombier 	||  lt->ntyp == C_CODE
141312a1df1SDavid du Colombier 	||  lt->ntyp == C_EXPR
1427dd7cddfSDavid du Colombier 	||  has_lab(el, 0)		/* any label at all */
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	||  lt->ntyp == DO
1457dd7cddfSDavid du Colombier 	||  lt->ntyp == UNLESS
1467dd7cddfSDavid du Colombier 	||  lt->ntyp == D_STEP
1477dd7cddfSDavid du Colombier 	||  lt->ntyp == ELSE
1487dd7cddfSDavid du Colombier 	||  lt->ntyp == '@'
1497dd7cddfSDavid du Colombier 	||  lt->ntyp == 'c'
1507dd7cddfSDavid du Colombier 	||  lt->ntyp == 'r'
1517dd7cddfSDavid du Colombier 	||  lt->ntyp == 's')
1527dd7cddfSDavid du Colombier 		return 0;
153312a1df1SDavid du Colombier 
1547dd7cddfSDavid du Colombier 	if (!(el->status&(2|4)))	/* not atomic */
1557dd7cddfSDavid du Colombier 	{	int unsafe = (el->status&I_GLOB)?1:has_global(el->n);
1567dd7cddfSDavid du Colombier 		if (unsafe)
1577dd7cddfSDavid du Colombier 			return 0;
1587dd7cddfSDavid du Colombier 	}
1597dd7cddfSDavid du Colombier 
1607dd7cddfSDavid du Colombier 	return 1;
1617dd7cddfSDavid du Colombier }
1627dd7cddfSDavid du Colombier 
1637dd7cddfSDavid du Colombier static int
canfill_in(FSM_trans * v)1647dd7cddfSDavid du Colombier canfill_in(FSM_trans *v)
1657dd7cddfSDavid du Colombier {	Element	*el = v->step;
1667dd7cddfSDavid du Colombier 	Lextok	*lt = v->step->n;
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier 	if (!lt				/* dead end */
1697dd7cddfSDavid du Colombier 	||  v->nxt			/* has alternatives */
1707dd7cddfSDavid du Colombier 	||  el->esc			/* has an escape */
1717dd7cddfSDavid du Colombier 	||  (el->status&CHECK2))	/* remotely referenced */
1727dd7cddfSDavid du Colombier 		return 0;
1737dd7cddfSDavid du Colombier 
1747dd7cddfSDavid du Colombier 	if (!(el->status&(2|4))		/* not atomic */
1757dd7cddfSDavid du Colombier 	&&  ((el->status&I_GLOB)
1767dd7cddfSDavid du Colombier 	||   has_global(el->n)))	/* and not safe */
1777dd7cddfSDavid du Colombier 		return 0;
1787dd7cddfSDavid du Colombier 
1797dd7cddfSDavid du Colombier 	return 1;
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier static int
pushbuild(FSM_trans * v)1837dd7cddfSDavid du Colombier pushbuild(FSM_trans *v)
1847dd7cddfSDavid du Colombier {	BuildStack *b;
1857dd7cddfSDavid du Colombier 
1867dd7cddfSDavid du Colombier 	for (b = bs; b; b = b->nxt)
1877dd7cddfSDavid du Colombier 		if (b->t == v)
1887dd7cddfSDavid du Colombier 			return 0;
1897dd7cddfSDavid du Colombier 	if (bf)
1907dd7cddfSDavid du Colombier 	{	b = bf;
1917dd7cddfSDavid du Colombier 		bf = bf->nxt;
1927dd7cddfSDavid du Colombier 	} else
1937dd7cddfSDavid du Colombier 		b = (BuildStack *) emalloc(sizeof(BuildStack));
1947dd7cddfSDavid du Colombier 	b->t = v;
1957dd7cddfSDavid du Colombier 	b->nxt = bs;
1967dd7cddfSDavid du Colombier 	bs = b;
1977dd7cddfSDavid du Colombier 	return 1;
1987dd7cddfSDavid du Colombier }
1997dd7cddfSDavid du Colombier 
2007dd7cddfSDavid du Colombier static void
popbuild(void)2017dd7cddfSDavid du Colombier popbuild(void)
2027dd7cddfSDavid du Colombier {	BuildStack *f;
2037dd7cddfSDavid du Colombier 	if (!bs)
2047dd7cddfSDavid du Colombier 		fatal("cannot happen, popbuild", (char *) 0);
2057dd7cddfSDavid du Colombier 	f = bs;
2067dd7cddfSDavid du Colombier 	bs = bs->nxt;
2077dd7cddfSDavid du Colombier 	f->nxt = bf;
2087dd7cddfSDavid du Colombier 	bf = f;				/* freelist */
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier 
2117dd7cddfSDavid du Colombier static int
build_step(FSM_trans * v)2127dd7cddfSDavid du Colombier build_step(FSM_trans *v)
2137dd7cddfSDavid du Colombier {	FSM_state *f;
214*00d97012SDavid du Colombier 	Element	*el;
215312a1df1SDavid du Colombier #if 0
2167dd7cddfSDavid du Colombier 	Lextok	*lt = ZN;
217312a1df1SDavid du Colombier #endif
218*00d97012SDavid du Colombier 	int	st;
2197dd7cddfSDavid du Colombier 	int	r;
2207dd7cddfSDavid du Colombier 
221*00d97012SDavid du Colombier 	if (!v) return -1;
222*00d97012SDavid du Colombier 
223*00d97012SDavid du Colombier 	el = v->step;
224*00d97012SDavid du Colombier 	st = v->to;
225*00d97012SDavid du Colombier 
2267dd7cddfSDavid du Colombier 	if (!el) return -1;
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier 	if (v->step->merge)
2297dd7cddfSDavid du Colombier 		return v->step->merge;	/* already done */
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier 	if (!eligible(v))		/* non-blocking */
2327dd7cddfSDavid du Colombier 		return -1;
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier 	if (!pushbuild(v))		/* cycle detected */
2357dd7cddfSDavid du Colombier 		return -1;		/* break cycle */
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier 	f = fsm_tbl[st];
2387dd7cddfSDavid du Colombier #if 0
239312a1df1SDavid du Colombier 	lt = v->step->n;
2407dd7cddfSDavid du Colombier 	if (verbose&32)
2417dd7cddfSDavid du Colombier 	{	if (++howdeep == 1)
242*00d97012SDavid du Colombier 			printf("spin: %s:%d, merge:\n", lt->fn->name, lt->ln);
2437dd7cddfSDavid du Colombier 		printf("\t[%d] <seqno %d>\t", howdeep, el->seqno);
2447dd7cddfSDavid du Colombier 		comment(stdout, lt, 0);
2457dd7cddfSDavid du Colombier 		printf(";\n");
2467dd7cddfSDavid du Colombier 	}
2477dd7cddfSDavid du Colombier #endif
2487dd7cddfSDavid du Colombier 	r = build_step(f->t);
2497dd7cddfSDavid du Colombier 	v->step->merge = (r == -1) ? st : r;
2507dd7cddfSDavid du Colombier #if 0
2517dd7cddfSDavid du Colombier 	if (verbose&32)
252312a1df1SDavid du Colombier 	{	printf("	merge value: %d (st=%d,r=%d, line %d)\n",
253312a1df1SDavid du Colombier 			v->step->merge, st, r, el->n->ln);
2547dd7cddfSDavid du Colombier 		howdeep--;
255312a1df1SDavid du Colombier 	}
2567dd7cddfSDavid du Colombier #endif
2577dd7cddfSDavid du Colombier 	popbuild();
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier 	return v->step->merge;
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier static void
FSM_MERGER(void)263*00d97012SDavid du Colombier FSM_MERGER(/* char *pname */ void)	/* find candidates for safely merging steps */
2647dd7cddfSDavid du Colombier {	FSM_state *f, *g;
2657dd7cddfSDavid du Colombier 	FSM_trans *t;
2667dd7cddfSDavid du Colombier 	Lextok	*lt;
2677dd7cddfSDavid du Colombier 
2687dd7cddfSDavid du Colombier 	for (f = fsm; f; f = f->nxt)		/* all states */
2697dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)		/* all edges */
2707dd7cddfSDavid du Colombier 	{	if (!t->step) continue;		/* happens with 'unless' */
2717dd7cddfSDavid du Colombier 
2727dd7cddfSDavid du Colombier 		t->step->merge_in = f->in;	/* ?? */
2737dd7cddfSDavid du Colombier 
2747dd7cddfSDavid du Colombier 		if (t->step->merge)
2757dd7cddfSDavid du Colombier 			continue;
2767dd7cddfSDavid du Colombier 		lt = t->step->n;
2777dd7cddfSDavid du Colombier 
2787dd7cddfSDavid du Colombier 		if (lt->ntyp == 'c'
2797dd7cddfSDavid du Colombier 		||  lt->ntyp == 'r'
2807dd7cddfSDavid du Colombier 		||  lt->ntyp == 's')	/* blocking stmnts */
2817dd7cddfSDavid du Colombier 			continue;	/* handled in 2nd scan */
2827dd7cddfSDavid du Colombier 
2837dd7cddfSDavid du Colombier 		if (!eligible(t))
2847dd7cddfSDavid du Colombier 			continue;
2857dd7cddfSDavid du Colombier 
2867dd7cddfSDavid du Colombier 		g = fsm_tbl[t->to];
287*00d97012SDavid du Colombier 		if (!g || !eligible(g->t))
2887dd7cddfSDavid du Colombier 		{
2897dd7cddfSDavid du Colombier #define SINGLES
2907dd7cddfSDavid du Colombier #ifdef SINGLES
2917dd7cddfSDavid du Colombier 			t->step->merge_single = t->to;
2927dd7cddfSDavid du Colombier #if 0
2937dd7cddfSDavid du Colombier 			if ((verbose&32))
294*00d97012SDavid du Colombier 			{	printf("spin: %s:%d, merge_single:\n\t<seqno %d>\t",
2957dd7cddfSDavid du Colombier 					t->step->n->fn->name,
2967dd7cddfSDavid du Colombier 					t->step->n->ln,
2977dd7cddfSDavid du Colombier 					t->step->seqno);
2987dd7cddfSDavid du Colombier 				comment(stdout, t->step->n, 0);
2997dd7cddfSDavid du Colombier 				printf(";\n");
3007dd7cddfSDavid du Colombier 			}
3017dd7cddfSDavid du Colombier #endif
3027dd7cddfSDavid du Colombier #endif
3037dd7cddfSDavid du Colombier 			/* t is an isolated eligible step:
3047dd7cddfSDavid du Colombier 			 *
3057dd7cddfSDavid du Colombier 			 * a merge_start can connect to a proper
3067dd7cddfSDavid du Colombier 			 * merge chain or to a merge_single
3077dd7cddfSDavid du Colombier 			 * a merge chain can be preceded by
3087dd7cddfSDavid du Colombier 			 * a merge_start, but not by a merge_single
3097dd7cddfSDavid du Colombier 			 */
3107dd7cddfSDavid du Colombier 
3117dd7cddfSDavid du Colombier 			continue;
3127dd7cddfSDavid du Colombier 		}
3137dd7cddfSDavid du Colombier 
3147dd7cddfSDavid du Colombier 		(void) build_step(t);
3157dd7cddfSDavid du Colombier 	}
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 	/* 2nd scan -- find possible merge_starts */
3187dd7cddfSDavid du Colombier 
3197dd7cddfSDavid du Colombier 	for (f = fsm; f; f = f->nxt)		/* all states */
3207dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)		/* all edges */
3217dd7cddfSDavid du Colombier 	{	if (!t->step || t->step->merge)
3227dd7cddfSDavid du Colombier 			continue;
3237dd7cddfSDavid du Colombier 
3247dd7cddfSDavid du Colombier 		lt = t->step->n;
325312a1df1SDavid du Colombier #if 0
326312a1df1SDavid du Colombier 	4.1.3:
327312a1df1SDavid du Colombier 	an rv send operation inside an atomic, *loses* atomicity
328312a1df1SDavid du Colombier 	when executed
329312a1df1SDavid du Colombier 	and should therefore never be merged with a subsequent
330312a1df1SDavid du Colombier 	statement within the atomic sequence
331312a1df1SDavid du Colombier 	the same is not true for non-rv send operations
332312a1df1SDavid du Colombier #endif
3337dd7cddfSDavid du Colombier 
334312a1df1SDavid du Colombier 		if (lt->ntyp == 'c'	/* potentially blocking stmnts */
3357dd7cddfSDavid du Colombier 		||  lt->ntyp == 'r'
336312a1df1SDavid du Colombier 		||  (lt->ntyp == 's' && u_sync == 0))	/* added !u_sync in 4.1.3 */
337312a1df1SDavid du Colombier 		{	if (!canfill_in(t))		/* atomic, non-global, etc. */
3387dd7cddfSDavid du Colombier 				continue;
3397dd7cddfSDavid du Colombier 
3407dd7cddfSDavid du Colombier 			g = fsm_tbl[t->to];
3417dd7cddfSDavid du Colombier 			if (!g || !g->t || !g->t->step)
3427dd7cddfSDavid du Colombier 				continue;
3437dd7cddfSDavid du Colombier 			if (g->t->step->merge)
3447dd7cddfSDavid du Colombier 				t->step->merge_start = g->t->step->merge;
3457dd7cddfSDavid du Colombier #ifdef SINGLES
3467dd7cddfSDavid du Colombier 			else if (g->t->step->merge_single)
3477dd7cddfSDavid du Colombier 				t->step->merge_start = g->t->step->merge_single;
3487dd7cddfSDavid du Colombier #endif
3497dd7cddfSDavid du Colombier #if 0
3507dd7cddfSDavid du Colombier 			if ((verbose&32)
3517dd7cddfSDavid du Colombier 			&& t->step->merge_start)
352*00d97012SDavid du Colombier 			{	printf("spin: %s:%d, merge_START:\n\t<seqno %d>\t",
353*00d97012SDavid du Colombier 						lt->fn->name, lt->ln,
3547dd7cddfSDavid du Colombier 						t->step->seqno);
3557dd7cddfSDavid du Colombier 				comment(stdout, lt, 0);
3567dd7cddfSDavid du Colombier 				printf(";\n");
3577dd7cddfSDavid du Colombier 			}
3587dd7cddfSDavid du Colombier #endif
3597dd7cddfSDavid du Colombier 		}
3607dd7cddfSDavid du Colombier 	}
3617dd7cddfSDavid du Colombier }
3627dd7cddfSDavid du Colombier 
3637dd7cddfSDavid du Colombier static void
FSM_ANA(void)3647dd7cddfSDavid du Colombier FSM_ANA(void)
3657dd7cddfSDavid du Colombier {	FSM_state *f;
3667dd7cddfSDavid du Colombier 	FSM_trans *t;
3677dd7cddfSDavid du Colombier 	FSM_use *u, *v, *w;
3687dd7cddfSDavid du Colombier 	int n;
3697dd7cddfSDavid du Colombier 
3707dd7cddfSDavid du Colombier 	for (f = fsm; f; f = f->nxt)		/* all states */
3717dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)		/* all edges */
3727dd7cddfSDavid du Colombier 	for (n = 0; n < 2; n++)			/* reads and writes */
3737dd7cddfSDavid du Colombier 	for (u = t->Val[n]; u; u = u->nxt)
3747dd7cddfSDavid du Colombier 	{	if (!u->var->context	/* global */
3757dd7cddfSDavid du Colombier 		||   u->var->type == CHAN
3767dd7cddfSDavid du Colombier 		||   u->var->type == STRUCT)
3777dd7cddfSDavid du Colombier 			continue;
3787dd7cddfSDavid du Colombier 		new_dfs();
3797dd7cddfSDavid du Colombier 		if (FSM_DFS(t->to, u))	/* cannot hit read before hitting write */
3807dd7cddfSDavid du Colombier 			u->special = n+1;	/* means, reset to 0 after use */
3817dd7cddfSDavid du Colombier 	}
3827dd7cddfSDavid du Colombier 
383312a1df1SDavid du Colombier 	if (!export_ast)
3847dd7cddfSDavid du Colombier 	for (f = fsm; f; f = f->nxt)
3857dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)
3867dd7cddfSDavid du Colombier 	for (n = 0; n < 2; n++)
3877dd7cddfSDavid du Colombier 	for (u = t->Val[n], w = (FSM_use *) 0; u; )
3887dd7cddfSDavid du Colombier 	{	if (u->special)
3897dd7cddfSDavid du Colombier 		{	v = u->nxt;
3907dd7cddfSDavid du Colombier 			if (!w)			/* remove from list */
3917dd7cddfSDavid du Colombier 				t->Val[n] = v;
3927dd7cddfSDavid du Colombier 			else
3937dd7cddfSDavid du Colombier 				w->nxt = v;
394312a1df1SDavid du Colombier #if q
3957dd7cddfSDavid du Colombier 			if (verbose&32)
3967dd7cddfSDavid du Colombier 			{	printf("%s : %3d:  %d -> %d \t",
3977dd7cddfSDavid du Colombier 					t->step->n->fn->name,
3987dd7cddfSDavid du Colombier 					t->step->n->ln,
3997dd7cddfSDavid du Colombier 					f->from,
4007dd7cddfSDavid du Colombier 					t->to);
4017dd7cddfSDavid du Colombier 				comment(stdout, t->step->n, 0);
4027dd7cddfSDavid du Colombier 				printf("\t%c%d: %s\n", n==0?'R':'L',
4037dd7cddfSDavid du Colombier 					u->special, u->var->name);
4047dd7cddfSDavid du Colombier 			}
4057dd7cddfSDavid du Colombier #endif
4067dd7cddfSDavid du Colombier 			if (good_dead(t->step, u))
4077dd7cddfSDavid du Colombier 			{	u->nxt = t->step->dead;	/* insert into dead */
4087dd7cddfSDavid du Colombier 				t->step->dead = u;
4097dd7cddfSDavid du Colombier 			}
4107dd7cddfSDavid du Colombier 			u = v;
4117dd7cddfSDavid du Colombier 		} else
4127dd7cddfSDavid du Colombier 		{	w = u;
4137dd7cddfSDavid du Colombier 			u = u->nxt;
4147dd7cddfSDavid du Colombier 	}	}
4157dd7cddfSDavid du Colombier }
4167dd7cddfSDavid du Colombier 
417312a1df1SDavid du Colombier void
rel_use(FSM_use * u)4187dd7cddfSDavid du Colombier rel_use(FSM_use *u)
4197dd7cddfSDavid du Colombier {
4207dd7cddfSDavid du Colombier 	if (!u) return;
4217dd7cddfSDavid du Colombier 	rel_use(u->nxt);
4227dd7cddfSDavid du Colombier 	u->var = (Symbol *) 0;
4237dd7cddfSDavid du Colombier 	u->special = 0;
4247dd7cddfSDavid du Colombier 	u->nxt = use_free;
4257dd7cddfSDavid du Colombier 	use_free = u;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier 
4287dd7cddfSDavid du Colombier static void
rel_trans(FSM_trans * t)4297dd7cddfSDavid du Colombier rel_trans(FSM_trans *t)
4307dd7cddfSDavid du Colombier {
4317dd7cddfSDavid du Colombier 	if (!t) return;
4327dd7cddfSDavid du Colombier 	rel_trans(t->nxt);
4337dd7cddfSDavid du Colombier 	rel_use(t->Val[0]);
4347dd7cddfSDavid du Colombier 	rel_use(t->Val[1]);
4357dd7cddfSDavid du Colombier 	t->Val[0] = t->Val[1] = (FSM_use *) 0;
4367dd7cddfSDavid du Colombier 	t->nxt = trans_free;
4377dd7cddfSDavid du Colombier 	trans_free = t;
4387dd7cddfSDavid du Colombier }
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier static void
rel_state(FSM_state * f)4417dd7cddfSDavid du Colombier rel_state(FSM_state *f)
4427dd7cddfSDavid du Colombier {
4437dd7cddfSDavid du Colombier 	if (!f) return;
4447dd7cddfSDavid du Colombier 	rel_state(f->nxt);
4457dd7cddfSDavid du Colombier 	rel_trans(f->t);
4467dd7cddfSDavid du Colombier 	f->t = (FSM_trans *) 0;
4477dd7cddfSDavid du Colombier 	f->nxt = fsm_free;
4487dd7cddfSDavid du Colombier 	fsm_free = f;
4497dd7cddfSDavid du Colombier }
4507dd7cddfSDavid du Colombier 
4517dd7cddfSDavid du Colombier static void
FSM_DEL(void)4527dd7cddfSDavid du Colombier FSM_DEL(void)
4537dd7cddfSDavid du Colombier {
4547dd7cddfSDavid du Colombier 	rel_state(fsm);
4557dd7cddfSDavid du Colombier 	fsm = (FSM_state *) 0;
4567dd7cddfSDavid du Colombier }
4577dd7cddfSDavid du Colombier 
4587dd7cddfSDavid du Colombier static FSM_state *
mkstate(int s)4597dd7cddfSDavid du Colombier mkstate(int s)
4607dd7cddfSDavid du Colombier {	FSM_state *f;
4617dd7cddfSDavid du Colombier 
4627dd7cddfSDavid du Colombier 	/* fsm_tbl isn't allocated yet */
4637dd7cddfSDavid du Colombier 	for (f = fsm; f; f = f->nxt)
4647dd7cddfSDavid du Colombier 		if (f->from == s)
4657dd7cddfSDavid du Colombier 			break;
4667dd7cddfSDavid du Colombier 	if (!f)
4677dd7cddfSDavid du Colombier 	{	if (fsm_free)
4687dd7cddfSDavid du Colombier 		{	f = fsm_free;
4697dd7cddfSDavid du Colombier 			memset(f, 0, sizeof(FSM_state));
4707dd7cddfSDavid du Colombier 			fsm_free = fsm_free->nxt;
4717dd7cddfSDavid du Colombier 		} else
4727dd7cddfSDavid du Colombier 			f = (FSM_state *) emalloc(sizeof(FSM_state));
4737dd7cddfSDavid du Colombier 		f->from = s;
4747dd7cddfSDavid du Colombier 		f->t = (FSM_trans *) 0;
4757dd7cddfSDavid du Colombier 		f->nxt = fsm;
4767dd7cddfSDavid du Colombier 		fsm = f;
4777dd7cddfSDavid du Colombier 		if (s > max_st_id)
4787dd7cddfSDavid du Colombier 			max_st_id = s;
4797dd7cddfSDavid du Colombier 	}
4807dd7cddfSDavid du Colombier 	return f;
4817dd7cddfSDavid du Colombier }
4827dd7cddfSDavid du Colombier 
483312a1df1SDavid du Colombier static FSM_trans *
get_trans(int to)484312a1df1SDavid du Colombier get_trans(int to)
485312a1df1SDavid du Colombier {	FSM_trans *t;
4867dd7cddfSDavid du Colombier 
4877dd7cddfSDavid du Colombier 	if (trans_free)
4887dd7cddfSDavid du Colombier 	{	t = trans_free;
4897dd7cddfSDavid du Colombier 		memset(t, 0, sizeof(FSM_trans));
4907dd7cddfSDavid du Colombier 		trans_free = trans_free->nxt;
4917dd7cddfSDavid du Colombier 	} else
4927dd7cddfSDavid du Colombier 		t = (FSM_trans *) emalloc(sizeof(FSM_trans));
493312a1df1SDavid du Colombier 
4947dd7cddfSDavid du Colombier 	t->to = to;
495312a1df1SDavid du Colombier 	return t;
496312a1df1SDavid du Colombier }
497312a1df1SDavid du Colombier 
498312a1df1SDavid du Colombier static void
FSM_EDGE(int from,int to,Element * e)499312a1df1SDavid du Colombier FSM_EDGE(int from, int to, Element *e)
500312a1df1SDavid du Colombier {	FSM_state *f;
501312a1df1SDavid du Colombier 	FSM_trans *t;
502312a1df1SDavid du Colombier 
503312a1df1SDavid du Colombier 	f = mkstate(from);	/* find it or else make it */
504312a1df1SDavid du Colombier 	t = get_trans(to);
505312a1df1SDavid du Colombier 
5067dd7cddfSDavid du Colombier 	t->step = e;
5077dd7cddfSDavid du Colombier 	t->nxt = f->t;
5087dd7cddfSDavid du Colombier 	f->t = t;
5097dd7cddfSDavid du Colombier 
5107dd7cddfSDavid du Colombier 	f = mkstate(to);
5117dd7cddfSDavid du Colombier 	f->in++;
5127dd7cddfSDavid du Colombier 
513312a1df1SDavid du Colombier 	if (export_ast)
514312a1df1SDavid du Colombier 	{	t = get_trans(from);
515312a1df1SDavid du Colombier 		t->step = e;
516312a1df1SDavid du Colombier 		t->nxt = f->p;	/* from is a predecessor of to */
517312a1df1SDavid du Colombier 		f->p = t;
518312a1df1SDavid du Colombier 	}
519312a1df1SDavid du Colombier 
5207dd7cddfSDavid du Colombier 	if (t->step)
5217dd7cddfSDavid du Colombier 		ana_stmnt(t, t->step->n, 0);
5227dd7cddfSDavid du Colombier }
5237dd7cddfSDavid du Colombier 
5247dd7cddfSDavid du Colombier #define LVAL	1
5257dd7cddfSDavid du Colombier #define RVAL	0
5267dd7cddfSDavid du Colombier 
5277dd7cddfSDavid du Colombier static void
ana_var(FSM_trans * t,Lextok * now,int usage)5287dd7cddfSDavid du Colombier ana_var(FSM_trans *t, Lextok *now, int usage)
5297dd7cddfSDavid du Colombier {	FSM_use *u, *v;
5307dd7cddfSDavid du Colombier 
531312a1df1SDavid du Colombier 	if (!t || !now || !now->sym)
532312a1df1SDavid du Colombier 		return;
533312a1df1SDavid du Colombier 
534312a1df1SDavid du Colombier 	if (now->sym->name[0] == '_'
535312a1df1SDavid du Colombier 	&&  (strcmp(now->sym->name, "_") == 0
536312a1df1SDavid du Colombier 	||   strcmp(now->sym->name, "_pid") == 0
537312a1df1SDavid du Colombier 	||   strcmp(now->sym->name, "_last") == 0))
5387dd7cddfSDavid du Colombier 		return;
5397dd7cddfSDavid du Colombier 
5407dd7cddfSDavid du Colombier 	v = t->Val[usage];
5417dd7cddfSDavid du Colombier 	for (u = v; u; u = u->nxt)
5427dd7cddfSDavid du Colombier 		if (u->var == now->sym)
5437dd7cddfSDavid du Colombier 			return;	/* it's already there */
5447dd7cddfSDavid du Colombier 
5457dd7cddfSDavid du Colombier 	if (!now->lft)
5467dd7cddfSDavid du Colombier 	{	/* not for array vars -- it's hard to tell statically
5477dd7cddfSDavid du Colombier 		   if the index would, at runtime, evaluate to the
5487dd7cddfSDavid du Colombier 		   same values at lval and rval references
5497dd7cddfSDavid du Colombier 		*/
5507dd7cddfSDavid du Colombier 		if (use_free)
5517dd7cddfSDavid du Colombier 		{	u = use_free;
5527dd7cddfSDavid du Colombier 			use_free = use_free->nxt;
5537dd7cddfSDavid du Colombier 		} else
5547dd7cddfSDavid du Colombier 			u = (FSM_use *) emalloc(sizeof(FSM_use));
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier 		u->var = now->sym;
5577dd7cddfSDavid du Colombier 		u->nxt = t->Val[usage];
5587dd7cddfSDavid du Colombier 		t->Val[usage] = u;
5597dd7cddfSDavid du Colombier 	} else
5607dd7cddfSDavid du Colombier 		 ana_stmnt(t, now->lft, RVAL);	/* index */
5617dd7cddfSDavid du Colombier 
5627dd7cddfSDavid du Colombier 	if (now->sym->type == STRUCT
5637dd7cddfSDavid du Colombier 	&&  now->rgt
5647dd7cddfSDavid du Colombier 	&&  now->rgt->lft)
5657dd7cddfSDavid du Colombier 		ana_var(t, now->rgt->lft, usage);
5667dd7cddfSDavid du Colombier }
5677dd7cddfSDavid du Colombier 
5687dd7cddfSDavid du Colombier static void
ana_stmnt(FSM_trans * t,Lextok * now,int usage)5697dd7cddfSDavid du Colombier ana_stmnt(FSM_trans *t, Lextok *now, int usage)
5707dd7cddfSDavid du Colombier {	Lextok *v;
5717dd7cddfSDavid du Colombier 
5727dd7cddfSDavid du Colombier 	if (!t || !now) return;
5737dd7cddfSDavid du Colombier 
5747dd7cddfSDavid du Colombier 	switch (now->ntyp) {
5757dd7cddfSDavid du Colombier 	case '.':
5767dd7cddfSDavid du Colombier 	case BREAK:
5777dd7cddfSDavid du Colombier 	case GOTO:
5787dd7cddfSDavid du Colombier 	case CONST:
5797dd7cddfSDavid du Colombier 	case TIMEOUT:
5807dd7cddfSDavid du Colombier 	case NONPROGRESS:
5817dd7cddfSDavid du Colombier 	case  ELSE:
5827dd7cddfSDavid du Colombier 	case '@':
5837dd7cddfSDavid du Colombier 	case 'q':
5847dd7cddfSDavid du Colombier 	case IF:
5857dd7cddfSDavid du Colombier 	case DO:
5867dd7cddfSDavid du Colombier 	case ATOMIC:
5877dd7cddfSDavid du Colombier 	case NON_ATOMIC:
5887dd7cddfSDavid du Colombier 	case D_STEP:
589312a1df1SDavid du Colombier 	case C_CODE:
590312a1df1SDavid du Colombier 	case C_EXPR:
5917dd7cddfSDavid du Colombier 		break;
5927dd7cddfSDavid du Colombier 
5937dd7cddfSDavid du Colombier 	case '!':
5947dd7cddfSDavid du Colombier 	case UMIN:
5957dd7cddfSDavid du Colombier 	case '~':
5967dd7cddfSDavid du Colombier 	case ENABLED:
5977dd7cddfSDavid du Colombier 	case PC_VAL:
5987dd7cddfSDavid du Colombier 	case LEN:
5997dd7cddfSDavid du Colombier 	case FULL:
6007dd7cddfSDavid du Colombier 	case EMPTY:
6017dd7cddfSDavid du Colombier 	case NFULL:
6027dd7cddfSDavid du Colombier 	case NEMPTY:
6037dd7cddfSDavid du Colombier 	case ASSERT:
6047dd7cddfSDavid du Colombier 	case 'c':
6057dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
6067dd7cddfSDavid du Colombier 		break;
6077dd7cddfSDavid du Colombier 
6087dd7cddfSDavid du Colombier 	case '/':
6097dd7cddfSDavid du Colombier 	case '*':
6107dd7cddfSDavid du Colombier 	case '-':
6117dd7cddfSDavid du Colombier 	case '+':
6127dd7cddfSDavid du Colombier 	case '%':
6137dd7cddfSDavid du Colombier 	case '&':
6147dd7cddfSDavid du Colombier 	case '^':
6157dd7cddfSDavid du Colombier 	case '|':
6167dd7cddfSDavid du Colombier 	case LT:
6177dd7cddfSDavid du Colombier 	case GT:
6187dd7cddfSDavid du Colombier 	case LE:
6197dd7cddfSDavid du Colombier 	case GE:
6207dd7cddfSDavid du Colombier 	case NE:
6217dd7cddfSDavid du Colombier 	case EQ:
6227dd7cddfSDavid du Colombier 	case OR:
6237dd7cddfSDavid du Colombier 	case AND:
6247dd7cddfSDavid du Colombier 	case LSHIFT:
6257dd7cddfSDavid du Colombier 	case RSHIFT:
6267dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
6277dd7cddfSDavid du Colombier 		ana_stmnt(t, now->rgt, RVAL);
6287dd7cddfSDavid du Colombier 		break;
6297dd7cddfSDavid du Colombier 
6307dd7cddfSDavid du Colombier 	case ASGN:
6317dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, LVAL);
6327dd7cddfSDavid du Colombier 		ana_stmnt(t, now->rgt, RVAL);
6337dd7cddfSDavid du Colombier 		break;
6347dd7cddfSDavid du Colombier 
6357dd7cddfSDavid du Colombier 	case PRINT:
6367dd7cddfSDavid du Colombier 	case RUN:
6377dd7cddfSDavid du Colombier 		for (v = now->lft; v; v = v->rgt)
6387dd7cddfSDavid du Colombier 			ana_stmnt(t, v->lft, RVAL);
6397dd7cddfSDavid du Colombier 		break;
6407dd7cddfSDavid du Colombier 
641312a1df1SDavid du Colombier 	case PRINTM:
642312a1df1SDavid du Colombier 		if (now->lft && !now->lft->ismtyp)
643312a1df1SDavid du Colombier 			ana_stmnt(t, now->lft, RVAL);
644312a1df1SDavid du Colombier 		break;
645312a1df1SDavid du Colombier 
6467dd7cddfSDavid du Colombier 	case 's':
6477dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
6487dd7cddfSDavid du Colombier 		for (v = now->rgt; v; v = v->rgt)
6497dd7cddfSDavid du Colombier 			ana_stmnt(t, v->lft, RVAL);
6507dd7cddfSDavid du Colombier 		break;
6517dd7cddfSDavid du Colombier 
6527dd7cddfSDavid du Colombier 	case 'R':
6537dd7cddfSDavid du Colombier 	case 'r':
6547dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
6557dd7cddfSDavid du Colombier 		for (v = now->rgt; v; v = v->rgt)
6567dd7cddfSDavid du Colombier 		{	if (v->lft->ntyp == EVAL)
6577dd7cddfSDavid du Colombier 				ana_stmnt(t, v->lft->lft, RVAL);
6587dd7cddfSDavid du Colombier 			else
6597dd7cddfSDavid du Colombier 			if (v->lft->ntyp != CONST
6607dd7cddfSDavid du Colombier 			&&  now->ntyp != 'R')		/* was v->lft->ntyp */
6617dd7cddfSDavid du Colombier 				ana_stmnt(t, v->lft, LVAL);
6627dd7cddfSDavid du Colombier 		}
6637dd7cddfSDavid du Colombier 		break;
6647dd7cddfSDavid du Colombier 
6657dd7cddfSDavid du Colombier 	case '?':
6667dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
667312a1df1SDavid du Colombier 		if (now->rgt)
668312a1df1SDavid du Colombier 		{	ana_stmnt(t, now->rgt->lft, RVAL);
6697dd7cddfSDavid du Colombier 			ana_stmnt(t, now->rgt->rgt, RVAL);
670312a1df1SDavid du Colombier 		}
6717dd7cddfSDavid du Colombier 		break;
6727dd7cddfSDavid du Colombier 
6737dd7cddfSDavid du Colombier 	case NAME:
6747dd7cddfSDavid du Colombier 		ana_var(t, now, usage);
6757dd7cddfSDavid du Colombier 		break;
6767dd7cddfSDavid du Colombier 
6777dd7cddfSDavid du Colombier 	case   'p':	/* remote ref */
6787dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft->lft, RVAL);	/* process id */
6797dd7cddfSDavid du Colombier 		ana_var(t, now, RVAL);
6807dd7cddfSDavid du Colombier 		ana_var(t, now->rgt, RVAL);
6817dd7cddfSDavid du Colombier 		break;
6827dd7cddfSDavid du Colombier 
6837dd7cddfSDavid du Colombier 	default:
684*00d97012SDavid du Colombier 		printf("spin: %s:%d, bad node type %d (ana_stmnt)\n",
685*00d97012SDavid du Colombier 			now->fn->name, now->ln, now->ntyp);
6867dd7cddfSDavid du Colombier 		fatal("aborting", (char *) 0);
6877dd7cddfSDavid du Colombier 	}
6887dd7cddfSDavid du Colombier }
6897dd7cddfSDavid du Colombier 
6907dd7cddfSDavid du Colombier void
ana_src(int dataflow,int merger)691312a1df1SDavid du Colombier ana_src(int dataflow, int merger)	/* called from main.c and guided.c */
6927dd7cddfSDavid du Colombier {	ProcList *p;
6937dd7cddfSDavid du Colombier 	Element *e;
694312a1df1SDavid du Colombier #if 0
6957dd7cddfSDavid du Colombier 	int counter = 1;
696312a1df1SDavid du Colombier #endif
6977dd7cddfSDavid du Colombier 	for (p = rdy; p; p = p->nxt)
698*00d97012SDavid du Colombier 	{
6997dd7cddfSDavid du Colombier 		ana_seq(p->s);
7007dd7cddfSDavid du Colombier 		fsm_table();
7017dd7cddfSDavid du Colombier 
7027dd7cddfSDavid du Colombier 		e = p->s->frst;
7037dd7cddfSDavid du Colombier #if 0
7047dd7cddfSDavid du Colombier 		if (dataflow || merger)
7057dd7cddfSDavid du Colombier 		{	printf("spin: %d, optimizing '%s'",
7067dd7cddfSDavid du Colombier 				counter++, p->n->name);
7077dd7cddfSDavid du Colombier 			fflush(stdout);
7087dd7cddfSDavid du Colombier 		}
7097dd7cddfSDavid du Colombier #endif
7107dd7cddfSDavid du Colombier 		if (dataflow)
7117dd7cddfSDavid du Colombier 		{	FSM_ANA();
7127dd7cddfSDavid du Colombier 		}
7137dd7cddfSDavid du Colombier 		if (merger)
714*00d97012SDavid du Colombier 		{	FSM_MERGER(/* p->n->name */);
715312a1df1SDavid du Colombier 			huntele(e, e->status, -1)->merge_in = 1; /* start-state */
7167dd7cddfSDavid du Colombier #if 0
7177dd7cddfSDavid du Colombier 			printf("\n");
7187dd7cddfSDavid du Colombier #endif
7197dd7cddfSDavid du Colombier 		}
720312a1df1SDavid du Colombier 		if (export_ast)
721312a1df1SDavid du Colombier 			AST_store(p, huntele(e, e->status, -1)->seqno);
722312a1df1SDavid du Colombier 
7237dd7cddfSDavid du Colombier 		FSM_DEL();
7247dd7cddfSDavid du Colombier 	}
7257dd7cddfSDavid du Colombier 	for (e = Al_El; e; e = e->Nxt)
7267dd7cddfSDavid du Colombier 	{
7277dd7cddfSDavid du Colombier 		if (!(e->status&DONE) && (verbose&32))
7287dd7cddfSDavid du Colombier 		{	printf("unreachable code: ");
729*00d97012SDavid du Colombier 			printf("%s:%3d  ", e->n->fn->name, e->n->ln);
7307dd7cddfSDavid du Colombier 			comment(stdout, e->n, 0);
7317dd7cddfSDavid du Colombier 			printf("\n");
7327dd7cddfSDavid du Colombier 		}
7337dd7cddfSDavid du Colombier 		e->status &= ~DONE;
7347dd7cddfSDavid du Colombier 	}
735312a1df1SDavid du Colombier 	if (export_ast)
736312a1df1SDavid du Colombier 	{	AST_slice();
737*00d97012SDavid du Colombier 		alldone(0);	/* changed in 5.3.0: was exit(0) */
738312a1df1SDavid du Colombier 	}
7397dd7cddfSDavid du Colombier }
7407dd7cddfSDavid du Colombier 
7417dd7cddfSDavid du Colombier void
spit_recvs(FILE * f1,FILE * f2)742312a1df1SDavid du Colombier spit_recvs(FILE *f1, FILE *f2)	/* called from pangen2.c */
7437dd7cddfSDavid du Colombier {	Element *e;
7447dd7cddfSDavid du Colombier 	Sequence *s;
7457dd7cddfSDavid du Colombier 	extern int Unique;
7467dd7cddfSDavid du Colombier 
7477dd7cddfSDavid du Colombier 	fprintf(f1, "unsigned char Is_Recv[%d];\n", Unique);
7487dd7cddfSDavid du Colombier 
7497dd7cddfSDavid du Colombier 	fprintf(f2, "void\nset_recvs(void)\n{\n");
7507dd7cddfSDavid du Colombier 	for (e = Al_El; e; e = e->Nxt)
7517dd7cddfSDavid du Colombier 	{	if (!e->n) continue;
7527dd7cddfSDavid du Colombier 
7537dd7cddfSDavid du Colombier 		switch (e->n->ntyp) {
7547dd7cddfSDavid du Colombier 		case 'r':
7557dd7cddfSDavid du Colombier markit:			fprintf(f2, "\tIs_Recv[%d] = 1;\n", e->Seqno);
7567dd7cddfSDavid du Colombier 			break;
7577dd7cddfSDavid du Colombier 		case D_STEP:
7587dd7cddfSDavid du Colombier 			s = e->n->sl->this;
7597dd7cddfSDavid du Colombier 			switch (s->frst->n->ntyp) {
7607dd7cddfSDavid du Colombier 			case DO:
7617dd7cddfSDavid du Colombier 				fatal("unexpected: do at start of d_step", (char *) 0);
7627dd7cddfSDavid du Colombier 			case IF: /* conservative: fall through */
7637dd7cddfSDavid du Colombier 			case 'r': goto markit;
7647dd7cddfSDavid du Colombier 			}
7657dd7cddfSDavid du Colombier 			break;
7667dd7cddfSDavid du Colombier 		}
7677dd7cddfSDavid du Colombier 	}
7687dd7cddfSDavid du Colombier 	fprintf(f2, "}\n");
7697dd7cddfSDavid du Colombier 
7707dd7cddfSDavid du Colombier 	if (rvopt)
7717dd7cddfSDavid du Colombier 	{
7727dd7cddfSDavid du Colombier 	fprintf(f2, "int\nno_recvs(int me)\n{\n");
7737dd7cddfSDavid du Colombier 	fprintf(f2, "	int h; uchar ot; short tt;\n");
7747dd7cddfSDavid du Colombier 	fprintf(f2, "	Trans *t;\n");
7757dd7cddfSDavid du Colombier 	fprintf(f2, "	for (h = BASE; h < (int) now._nr_pr; h++)\n");
7767dd7cddfSDavid du Colombier 	fprintf(f2, "	{	if (h == me) continue;\n");
7777dd7cddfSDavid du Colombier 	fprintf(f2, "		tt = (short) ((P0 *)pptr(h))->_p;\n");
7787dd7cddfSDavid du Colombier 	fprintf(f2, "		ot = (uchar) ((P0 *)pptr(h))->_t;\n");
7797dd7cddfSDavid du Colombier 	fprintf(f2, "		for (t = trans[ot][tt]; t; t = t->nxt)\n");
7807dd7cddfSDavid du Colombier 	fprintf(f2, "			if (Is_Recv[t->t_id]) return 0;\n");
7817dd7cddfSDavid du Colombier 	fprintf(f2, "	}\n");
7827dd7cddfSDavid du Colombier 	fprintf(f2, "	return 1;\n");
7837dd7cddfSDavid du Colombier 	fprintf(f2, "}\n");
7847dd7cddfSDavid du Colombier 	}
7857dd7cddfSDavid du Colombier }
7867dd7cddfSDavid du Colombier 
7877dd7cddfSDavid du Colombier static void
ana_seq(Sequence * s)7887dd7cddfSDavid du Colombier ana_seq(Sequence *s)
7897dd7cddfSDavid du Colombier {	SeqList *h;
7907dd7cddfSDavid du Colombier 	Sequence *t;
7917dd7cddfSDavid du Colombier 	Element *e, *g;
7927dd7cddfSDavid du Colombier 	int From, To;
7937dd7cddfSDavid du Colombier 
7947dd7cddfSDavid du Colombier 	for (e = s->frst; e; e = e->nxt)
7957dd7cddfSDavid du Colombier 	{	if (e->status & DONE)
7967dd7cddfSDavid du Colombier 			goto checklast;
7977dd7cddfSDavid du Colombier 
7987dd7cddfSDavid du Colombier 		e->status |= DONE;
7997dd7cddfSDavid du Colombier 
8007dd7cddfSDavid du Colombier 		From = e->seqno;
8017dd7cddfSDavid du Colombier 
8027dd7cddfSDavid du Colombier 		if (e->n->ntyp == UNLESS)
8037dd7cddfSDavid du Colombier 			ana_seq(e->sub->this);
8047dd7cddfSDavid du Colombier 		else if (e->sub)
8057dd7cddfSDavid du Colombier 		{	for (h = e->sub; h; h = h->nxt)
8067dd7cddfSDavid du Colombier 			{	g = huntstart(h->this->frst);
8077dd7cddfSDavid du Colombier 				To = g->seqno;
8087dd7cddfSDavid du Colombier 
8097dd7cddfSDavid du Colombier 				if (g->n->ntyp != 'c'
8107dd7cddfSDavid du Colombier 				||  g->n->lft->ntyp != CONST
8117dd7cddfSDavid du Colombier 				||  g->n->lft->val != 0
8127dd7cddfSDavid du Colombier 				||  g->esc)
8137dd7cddfSDavid du Colombier 					FSM_EDGE(From, To, e);
8147dd7cddfSDavid du Colombier 				/* else it's a dead link */
8157dd7cddfSDavid du Colombier 			}
8167dd7cddfSDavid du Colombier 			for (h = e->sub; h; h = h->nxt)
8177dd7cddfSDavid du Colombier 				ana_seq(h->this);
8187dd7cddfSDavid du Colombier 		} else if (e->n->ntyp == ATOMIC
8197dd7cddfSDavid du Colombier 			||  e->n->ntyp == D_STEP
8207dd7cddfSDavid du Colombier 			||  e->n->ntyp == NON_ATOMIC)
8217dd7cddfSDavid du Colombier 		{
8227dd7cddfSDavid du Colombier 			t = e->n->sl->this;
8237dd7cddfSDavid du Colombier 			g = huntstart(t->frst);
8247dd7cddfSDavid du Colombier 			t->last->nxt = e->nxt;
8257dd7cddfSDavid du Colombier 			To = g->seqno;
8267dd7cddfSDavid du Colombier 			FSM_EDGE(From, To, e);
8277dd7cddfSDavid du Colombier 
8287dd7cddfSDavid du Colombier 			ana_seq(t);
8297dd7cddfSDavid du Colombier 		} else
8307dd7cddfSDavid du Colombier 		{	if (e->n->ntyp == GOTO)
8317dd7cddfSDavid du Colombier 			{	g = get_lab(e->n, 1);
832312a1df1SDavid du Colombier 				g = huntele(g, e->status, -1);
8337dd7cddfSDavid du Colombier 				To = g->seqno;
8347dd7cddfSDavid du Colombier 			} else if (e->nxt)
835312a1df1SDavid du Colombier 			{	g = huntele(e->nxt, e->status, -1);
8367dd7cddfSDavid du Colombier 				To = g->seqno;
8377dd7cddfSDavid du Colombier 			} else
8387dd7cddfSDavid du Colombier 				To = 0;
8397dd7cddfSDavid du Colombier 
8407dd7cddfSDavid du Colombier 			FSM_EDGE(From, To, e);
8417dd7cddfSDavid du Colombier 
8427dd7cddfSDavid du Colombier 			if (e->esc
8437dd7cddfSDavid du Colombier 			&&  e->n->ntyp != GOTO
8447dd7cddfSDavid du Colombier 			&&  e->n->ntyp != '.')
8457dd7cddfSDavid du Colombier 			for (h = e->esc; h; h = h->nxt)
8467dd7cddfSDavid du Colombier 			{	g = huntstart(h->this->frst);
8477dd7cddfSDavid du Colombier 				To = g->seqno;
8487dd7cddfSDavid du Colombier 				FSM_EDGE(From, To, ZE);
8497dd7cddfSDavid du Colombier 				ana_seq(h->this);
8507dd7cddfSDavid du Colombier 			}
8517dd7cddfSDavid du Colombier 		}
8527dd7cddfSDavid du Colombier 
8537dd7cddfSDavid du Colombier checklast:	if (e == s->last)
8547dd7cddfSDavid du Colombier 			break;
8557dd7cddfSDavid du Colombier 	}
8567dd7cddfSDavid du Colombier }
857