xref: /plan9-contrib/sys/src/cmd/spin/pangen5.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
17dd7cddfSDavid du Colombier /***** spin: pangen5.c *****/
27dd7cddfSDavid du Colombier 
3*de2caf28SDavid du Colombier /*
4*de2caf28SDavid du Colombier  * This file is part of the public release of Spin. It is subject to the
5*de2caf28SDavid du Colombier  * terms in the LICENSE file that is included in this source directory.
6*de2caf28SDavid du Colombier  * Tool documentation is available at http://spinroot.com
7*de2caf28SDavid du Colombier  */
87dd7cddfSDavid du Colombier 
97dd7cddfSDavid du Colombier #include "spin.h"
107dd7cddfSDavid du Colombier #include "y.tab.h"
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier typedef struct BuildStack {
137dd7cddfSDavid du Colombier 	FSM_trans *t;
147dd7cddfSDavid du Colombier 	struct BuildStack *nxt;
157dd7cddfSDavid du Colombier } BuildStack;
167dd7cddfSDavid du Colombier 
17*de2caf28SDavid du Colombier extern ProcList	*ready;
18312a1df1SDavid du Colombier extern int verbose, eventmapnr, claimnr, rvopt, export_ast, u_sync;
197dd7cddfSDavid du Colombier extern Element *Al_El;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier static FSM_state *fsm_free;
227dd7cddfSDavid du Colombier static FSM_trans *trans_free;
237dd7cddfSDavid du Colombier static BuildStack *bs, *bf;
247dd7cddfSDavid du Colombier static int max_st_id;
257dd7cddfSDavid du Colombier static int cur_st_id;
26312a1df1SDavid du Colombier int o_max;
27*de2caf28SDavid du Colombier FSM_state *fsmx;
28312a1df1SDavid du Colombier FSM_state **fsm_tbl;
29312a1df1SDavid du Colombier FSM_use   *use_free;
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier static void ana_seq(Sequence *);
327dd7cddfSDavid du Colombier static void ana_stmnt(FSM_trans *, Lextok *, int);
337dd7cddfSDavid du Colombier 
34312a1df1SDavid du Colombier extern void AST_slice(void);
35312a1df1SDavid du Colombier extern void AST_store(ProcList *, int);
36312a1df1SDavid du Colombier extern int  has_global(Lextok *);
37312a1df1SDavid du Colombier extern void exit(int);
38312a1df1SDavid du Colombier 
39312a1df1SDavid du Colombier static void
fsm_table(void)407dd7cddfSDavid du Colombier fsm_table(void)
417dd7cddfSDavid du Colombier {	FSM_state *f;
427dd7cddfSDavid du Colombier 	max_st_id += 2;
437dd7cddfSDavid du Colombier 	/* fprintf(stderr, "omax %d, max=%d\n", o_max, max_st_id); */
447dd7cddfSDavid du Colombier 	if (o_max < max_st_id)
457dd7cddfSDavid du Colombier 	{	o_max = max_st_id;
467dd7cddfSDavid du Colombier 		fsm_tbl = (FSM_state **) emalloc(max_st_id * sizeof(FSM_state *));
477dd7cddfSDavid du Colombier 	} else
487dd7cddfSDavid du Colombier 		memset((char *)fsm_tbl, 0, max_st_id * sizeof(FSM_state *));
497dd7cddfSDavid du Colombier 	cur_st_id = max_st_id;
507dd7cddfSDavid du Colombier 	max_st_id = 0;
517dd7cddfSDavid du Colombier 
52*de2caf28SDavid du Colombier 	for (f = fsmx; f; f = f->nxt)
537dd7cddfSDavid du Colombier 		fsm_tbl[f->from] = f;
547dd7cddfSDavid du Colombier }
557dd7cddfSDavid du Colombier 
567dd7cddfSDavid du Colombier static int
FSM_DFS(int from,FSM_use * u)577dd7cddfSDavid du Colombier FSM_DFS(int from, FSM_use *u)
587dd7cddfSDavid du Colombier {	FSM_state *f;
597dd7cddfSDavid du Colombier 	FSM_trans *t;
607dd7cddfSDavid du Colombier 	FSM_use *v;
617dd7cddfSDavid du Colombier 	int n;
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier 	if (from == 0)
647dd7cddfSDavid du Colombier 		return 1;
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier 	f = fsm_tbl[from];
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier 	if (!f)
697dd7cddfSDavid du Colombier 	{	printf("cannot find state %d\n", from);
707dd7cddfSDavid du Colombier 		fatal("fsm_dfs: cannot happen\n", (char *) 0);
717dd7cddfSDavid du Colombier 	}
727dd7cddfSDavid du Colombier 
737dd7cddfSDavid du Colombier 	if (f->seen)
747dd7cddfSDavid du Colombier 		return 1;
757dd7cddfSDavid du Colombier 	f->seen = 1;
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)
787dd7cddfSDavid du Colombier 	{
797dd7cddfSDavid du Colombier 		for (n = 0; n < 2; n++)
807dd7cddfSDavid du Colombier 		for (v = t->Val[n]; v; v = v->nxt)
817dd7cddfSDavid du Colombier 			if (u->var == v->var)
827dd7cddfSDavid du Colombier 				return n;	/* a read or write */
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier 		if (!FSM_DFS(t->to, u))
857dd7cddfSDavid du Colombier 			return 0;
867dd7cddfSDavid du Colombier 	}
877dd7cddfSDavid du Colombier 	return 1;
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier static void
new_dfs(void)917dd7cddfSDavid du Colombier new_dfs(void)
927dd7cddfSDavid du Colombier {	int i;
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier 	for (i = 0; i < cur_st_id; i++)
957dd7cddfSDavid du Colombier 		if (fsm_tbl[i])
967dd7cddfSDavid du Colombier 			fsm_tbl[i]->seen = 0;
977dd7cddfSDavid du Colombier }
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier static int
good_dead(Element * e,FSM_use * u)1007dd7cddfSDavid du Colombier good_dead(Element *e, FSM_use *u)
1017dd7cddfSDavid du Colombier {
1027dd7cddfSDavid du Colombier 	switch (u->special) {
1037dd7cddfSDavid du Colombier 	case 2:	/* ok if it's a receive */
1047dd7cddfSDavid du Colombier 		if (e->n->ntyp == ASGN
1057dd7cddfSDavid du Colombier 		&&  e->n->rgt->ntyp == CONST
1067dd7cddfSDavid du Colombier 		&&  e->n->rgt->val == 0)
1077dd7cddfSDavid du Colombier 			return 0;
1087dd7cddfSDavid du Colombier 		break;
1097dd7cddfSDavid du Colombier 	case 1:	/* must be able to use oval */
1107dd7cddfSDavid du Colombier 		if (e->n->ntyp != 'c'
1117dd7cddfSDavid du Colombier 		&&  e->n->ntyp != 'r')
1127dd7cddfSDavid du Colombier 			return 0;	/* can't really happen */
1137dd7cddfSDavid du Colombier 		break;
1147dd7cddfSDavid du Colombier 	}
1157dd7cddfSDavid du Colombier 	return 1;
1167dd7cddfSDavid du Colombier }
1177dd7cddfSDavid du Colombier 
1187dd7cddfSDavid du Colombier #if 0
1197dd7cddfSDavid du Colombier static int howdeep = 0;
120312a1df1SDavid du Colombier #endif
1217dd7cddfSDavid du Colombier 
1227dd7cddfSDavid du Colombier static int
eligible(FSM_trans * v)1237dd7cddfSDavid du Colombier eligible(FSM_trans *v)
1247dd7cddfSDavid du Colombier {	Element	*el = ZE;
1257dd7cddfSDavid du Colombier 	Lextok	*lt = ZN;
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier 	if (v) el = v->step;
1287dd7cddfSDavid du Colombier 	if (el) lt = v->step->n;
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier 	if (!lt				/* dead end */
1317dd7cddfSDavid du Colombier 	||  v->nxt			/* has alternatives */
1327dd7cddfSDavid du Colombier 	||  el->esc			/* has an escape */
1337dd7cddfSDavid du Colombier 	||  (el->status&CHECK2)		/* remotely referenced */
1347dd7cddfSDavid du Colombier 	||  lt->ntyp == ATOMIC
1357dd7cddfSDavid du Colombier 	||  lt->ntyp == NON_ATOMIC	/* used for inlines -- should be able to handle this */
1367dd7cddfSDavid du Colombier 	||  lt->ntyp == IF
137312a1df1SDavid du Colombier 	||  lt->ntyp == C_CODE
138312a1df1SDavid du Colombier 	||  lt->ntyp == C_EXPR
1397dd7cddfSDavid du Colombier 	||  has_lab(el, 0)		/* any label at all */
140*de2caf28SDavid du Colombier 	||  lt->ntyp == SET_P		/* to prevent multiple set_p merges */
1417dd7cddfSDavid du Colombier 
1427dd7cddfSDavid du Colombier 	||  lt->ntyp == DO
1437dd7cddfSDavid du Colombier 	||  lt->ntyp == UNLESS
1447dd7cddfSDavid du Colombier 	||  lt->ntyp == D_STEP
1457dd7cddfSDavid du Colombier 	||  lt->ntyp == ELSE
1467dd7cddfSDavid du Colombier 	||  lt->ntyp == '@'
1477dd7cddfSDavid du Colombier 	||  lt->ntyp == 'c'
1487dd7cddfSDavid du Colombier 	||  lt->ntyp == 'r'
1497dd7cddfSDavid du Colombier 	||  lt->ntyp == 's')
1507dd7cddfSDavid du Colombier 		return 0;
151312a1df1SDavid du Colombier 
1527dd7cddfSDavid du Colombier 	if (!(el->status&(2|4)))	/* not atomic */
1537dd7cddfSDavid du Colombier 	{	int unsafe = (el->status&I_GLOB)?1:has_global(el->n);
1547dd7cddfSDavid du Colombier 		if (unsafe)
1557dd7cddfSDavid du Colombier 			return 0;
1567dd7cddfSDavid du Colombier 	}
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier 	return 1;
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier 
1617dd7cddfSDavid du Colombier static int
canfill_in(FSM_trans * v)1627dd7cddfSDavid du Colombier canfill_in(FSM_trans *v)
1637dd7cddfSDavid du Colombier {	Element	*el = v->step;
1647dd7cddfSDavid du Colombier 	Lextok	*lt = v->step->n;
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier 	if (!lt				/* dead end */
1677dd7cddfSDavid du Colombier 	||  v->nxt			/* has alternatives */
1687dd7cddfSDavid du Colombier 	||  el->esc			/* has an escape */
1697dd7cddfSDavid du Colombier 	||  (el->status&CHECK2))	/* remotely referenced */
1707dd7cddfSDavid du Colombier 		return 0;
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier 	if (!(el->status&(2|4))		/* not atomic */
1737dd7cddfSDavid du Colombier 	&&  ((el->status&I_GLOB)
1747dd7cddfSDavid du Colombier 	||   has_global(el->n)))	/* and not safe */
1757dd7cddfSDavid du Colombier 		return 0;
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier 	return 1;
1787dd7cddfSDavid du Colombier }
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier static int
pushbuild(FSM_trans * v)1817dd7cddfSDavid du Colombier pushbuild(FSM_trans *v)
1827dd7cddfSDavid du Colombier {	BuildStack *b;
1837dd7cddfSDavid du Colombier 
1847dd7cddfSDavid du Colombier 	for (b = bs; b; b = b->nxt)
1857dd7cddfSDavid du Colombier 		if (b->t == v)
1867dd7cddfSDavid du Colombier 			return 0;
1877dd7cddfSDavid du Colombier 	if (bf)
1887dd7cddfSDavid du Colombier 	{	b = bf;
1897dd7cddfSDavid du Colombier 		bf = bf->nxt;
1907dd7cddfSDavid du Colombier 	} else
1917dd7cddfSDavid du Colombier 		b = (BuildStack *) emalloc(sizeof(BuildStack));
1927dd7cddfSDavid du Colombier 	b->t = v;
1937dd7cddfSDavid du Colombier 	b->nxt = bs;
1947dd7cddfSDavid du Colombier 	bs = b;
1957dd7cddfSDavid du Colombier 	return 1;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier static void
popbuild(void)1997dd7cddfSDavid du Colombier popbuild(void)
2007dd7cddfSDavid du Colombier {	BuildStack *f;
2017dd7cddfSDavid du Colombier 	if (!bs)
2027dd7cddfSDavid du Colombier 		fatal("cannot happen, popbuild", (char *) 0);
2037dd7cddfSDavid du Colombier 	f = bs;
2047dd7cddfSDavid du Colombier 	bs = bs->nxt;
2057dd7cddfSDavid du Colombier 	f->nxt = bf;
2067dd7cddfSDavid du Colombier 	bf = f;				/* freelist */
2077dd7cddfSDavid du Colombier }
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier static int
build_step(FSM_trans * v)2107dd7cddfSDavid du Colombier build_step(FSM_trans *v)
2117dd7cddfSDavid du Colombier {	FSM_state *f;
21200d97012SDavid du Colombier 	Element	*el;
213312a1df1SDavid du Colombier #if 0
2147dd7cddfSDavid du Colombier 	Lextok	*lt = ZN;
215312a1df1SDavid du Colombier #endif
21600d97012SDavid du Colombier 	int	st;
2177dd7cddfSDavid du Colombier 	int	r;
2187dd7cddfSDavid du Colombier 
21900d97012SDavid du Colombier 	if (!v) return -1;
22000d97012SDavid du Colombier 
22100d97012SDavid du Colombier 	el = v->step;
22200d97012SDavid du Colombier 	st = v->to;
22300d97012SDavid du Colombier 
2247dd7cddfSDavid du Colombier 	if (!el) return -1;
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier 	if (v->step->merge)
2277dd7cddfSDavid du Colombier 		return v->step->merge;	/* already done */
2287dd7cddfSDavid du Colombier 
2297dd7cddfSDavid du Colombier 	if (!eligible(v))		/* non-blocking */
2307dd7cddfSDavid du Colombier 		return -1;
2317dd7cddfSDavid du Colombier 
2327dd7cddfSDavid du Colombier 	if (!pushbuild(v))		/* cycle detected */
2337dd7cddfSDavid du Colombier 		return -1;		/* break cycle */
2347dd7cddfSDavid du Colombier 
2357dd7cddfSDavid du Colombier 	f = fsm_tbl[st];
2367dd7cddfSDavid du Colombier #if 0
237312a1df1SDavid du Colombier 	lt = v->step->n;
2387dd7cddfSDavid du Colombier 	if (verbose&32)
2397dd7cddfSDavid du Colombier 	{	if (++howdeep == 1)
24000d97012SDavid du Colombier 			printf("spin: %s:%d, merge:\n", lt->fn->name, lt->ln);
2417dd7cddfSDavid du Colombier 		printf("\t[%d] <seqno %d>\t", howdeep, el->seqno);
2427dd7cddfSDavid du Colombier 		comment(stdout, lt, 0);
2437dd7cddfSDavid du Colombier 		printf(";\n");
2447dd7cddfSDavid du Colombier 	}
2457dd7cddfSDavid du Colombier #endif
2467dd7cddfSDavid du Colombier 	r = build_step(f->t);
2477dd7cddfSDavid du Colombier 	v->step->merge = (r == -1) ? st : r;
2487dd7cddfSDavid du Colombier #if 0
2497dd7cddfSDavid du Colombier 	if (verbose&32)
250312a1df1SDavid du Colombier 	{	printf("	merge value: %d (st=%d,r=%d, line %d)\n",
251312a1df1SDavid du Colombier 			v->step->merge, st, r, el->n->ln);
2527dd7cddfSDavid du Colombier 		howdeep--;
253312a1df1SDavid du Colombier 	}
2547dd7cddfSDavid du Colombier #endif
2557dd7cddfSDavid du Colombier 	popbuild();
2567dd7cddfSDavid du Colombier 
2577dd7cddfSDavid du Colombier 	return v->step->merge;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier static void
FSM_MERGER(void)26100d97012SDavid du Colombier FSM_MERGER(/* char *pname */ void)	/* find candidates for safely merging steps */
2627dd7cddfSDavid du Colombier {	FSM_state *f, *g;
2637dd7cddfSDavid du Colombier 	FSM_trans *t;
2647dd7cddfSDavid du Colombier 	Lextok	*lt;
2657dd7cddfSDavid du Colombier 
266*de2caf28SDavid du Colombier 	for (f = fsmx; f; f = f->nxt)		/* all states */
2677dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)		/* all edges */
2687dd7cddfSDavid du Colombier 	{	if (!t->step) continue;		/* happens with 'unless' */
2697dd7cddfSDavid du Colombier 
2707dd7cddfSDavid du Colombier 		t->step->merge_in = f->in;	/* ?? */
2717dd7cddfSDavid du Colombier 
2727dd7cddfSDavid du Colombier 		if (t->step->merge)
2737dd7cddfSDavid du Colombier 			continue;
2747dd7cddfSDavid du Colombier 		lt = t->step->n;
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier 		if (lt->ntyp == 'c'
2777dd7cddfSDavid du Colombier 		||  lt->ntyp == 'r'
2787dd7cddfSDavid du Colombier 		||  lt->ntyp == 's')	/* blocking stmnts */
2797dd7cddfSDavid du Colombier 			continue;	/* handled in 2nd scan */
2807dd7cddfSDavid du Colombier 
2817dd7cddfSDavid du Colombier 		if (!eligible(t))
2827dd7cddfSDavid du Colombier 			continue;
2837dd7cddfSDavid du Colombier 
2847dd7cddfSDavid du Colombier 		g = fsm_tbl[t->to];
28500d97012SDavid du Colombier 		if (!g || !eligible(g->t))
2867dd7cddfSDavid du Colombier 		{
2877dd7cddfSDavid du Colombier #define SINGLES
2887dd7cddfSDavid du Colombier #ifdef SINGLES
2897dd7cddfSDavid du Colombier 			t->step->merge_single = t->to;
2907dd7cddfSDavid du Colombier #if 0
2917dd7cddfSDavid du Colombier 			if ((verbose&32))
29200d97012SDavid du Colombier 			{	printf("spin: %s:%d, merge_single:\n\t<seqno %d>\t",
2937dd7cddfSDavid du Colombier 					t->step->n->fn->name,
2947dd7cddfSDavid du Colombier 					t->step->n->ln,
2957dd7cddfSDavid du Colombier 					t->step->seqno);
2967dd7cddfSDavid du Colombier 				comment(stdout, t->step->n, 0);
2977dd7cddfSDavid du Colombier 				printf(";\n");
2987dd7cddfSDavid du Colombier 			}
2997dd7cddfSDavid du Colombier #endif
3007dd7cddfSDavid du Colombier #endif
3017dd7cddfSDavid du Colombier 			/* t is an isolated eligible step:
3027dd7cddfSDavid du Colombier 			 *
3037dd7cddfSDavid du Colombier 			 * a merge_start can connect to a proper
3047dd7cddfSDavid du Colombier 			 * merge chain or to a merge_single
3057dd7cddfSDavid du Colombier 			 * a merge chain can be preceded by
3067dd7cddfSDavid du Colombier 			 * a merge_start, but not by a merge_single
3077dd7cddfSDavid du Colombier 			 */
3087dd7cddfSDavid du Colombier 
3097dd7cddfSDavid du Colombier 			continue;
3107dd7cddfSDavid du Colombier 		}
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier 		(void) build_step(t);
3137dd7cddfSDavid du Colombier 	}
3147dd7cddfSDavid du Colombier 
3157dd7cddfSDavid du Colombier 	/* 2nd scan -- find possible merge_starts */
3167dd7cddfSDavid du Colombier 
317*de2caf28SDavid du Colombier 	for (f = fsmx; f; f = f->nxt)		/* all states */
3187dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)		/* all edges */
3197dd7cddfSDavid du Colombier 	{	if (!t->step || t->step->merge)
3207dd7cddfSDavid du Colombier 			continue;
3217dd7cddfSDavid du Colombier 
3227dd7cddfSDavid du Colombier 		lt = t->step->n;
323312a1df1SDavid du Colombier #if 0
324312a1df1SDavid du Colombier 	4.1.3:
325*de2caf28SDavid du Colombier 	an rv send operation ('s') inside an atomic, *loses* atomicity
326*de2caf28SDavid du Colombier 	when executed, and should therefore never be merged with a subsequent
327312a1df1SDavid du Colombier 	statement within the atomic sequence
328*de2caf28SDavid du Colombier 	the same is not true for non-rv send operations;
329*de2caf28SDavid du Colombier 	6.2.2:
330*de2caf28SDavid du Colombier 	RUN statements can start a new process at a higher priority level
331*de2caf28SDavid du Colombier 	which interferes with statement merging, so it too is not a suitable
332*de2caf28SDavid du Colombier 	merge target
333312a1df1SDavid du Colombier #endif
3347dd7cddfSDavid du Colombier 
335*de2caf28SDavid du Colombier 		if ((lt->ntyp == 'c' && !any_oper(lt->lft, RUN)) /* 2nd clause 6.2.2 */
3367dd7cddfSDavid du Colombier 		||  lt->ntyp == 'r'
337312a1df1SDavid du Colombier 		||  (lt->ntyp == 's' && u_sync == 0))	/* added !u_sync in 4.1.3 */
338312a1df1SDavid du Colombier 		{	if (!canfill_in(t))		/* atomic, non-global, etc. */
3397dd7cddfSDavid du Colombier 				continue;
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 			g = fsm_tbl[t->to];
3427dd7cddfSDavid du Colombier 			if (!g || !g->t || !g->t->step)
3437dd7cddfSDavid du Colombier 				continue;
3447dd7cddfSDavid du Colombier 			if (g->t->step->merge)
3457dd7cddfSDavid du Colombier 				t->step->merge_start = g->t->step->merge;
3467dd7cddfSDavid du Colombier #ifdef SINGLES
3477dd7cddfSDavid du Colombier 			else if (g->t->step->merge_single)
3487dd7cddfSDavid du Colombier 				t->step->merge_start = g->t->step->merge_single;
3497dd7cddfSDavid du Colombier #endif
3507dd7cddfSDavid du Colombier #if 0
3517dd7cddfSDavid du Colombier 			if ((verbose&32)
3527dd7cddfSDavid du Colombier 			&& t->step->merge_start)
35300d97012SDavid du Colombier 			{	printf("spin: %s:%d, merge_START:\n\t<seqno %d>\t",
35400d97012SDavid du Colombier 						lt->fn->name, lt->ln,
3557dd7cddfSDavid du Colombier 						t->step->seqno);
3567dd7cddfSDavid du Colombier 				comment(stdout, lt, 0);
3577dd7cddfSDavid du Colombier 				printf(";\n");
3587dd7cddfSDavid du Colombier 			}
3597dd7cddfSDavid du Colombier #endif
3607dd7cddfSDavid du Colombier 		}
3617dd7cddfSDavid du Colombier 	}
3627dd7cddfSDavid du Colombier }
3637dd7cddfSDavid du Colombier 
3647dd7cddfSDavid du Colombier static void
FSM_ANA(void)3657dd7cddfSDavid du Colombier FSM_ANA(void)
3667dd7cddfSDavid du Colombier {	FSM_state *f;
3677dd7cddfSDavid du Colombier 	FSM_trans *t;
3687dd7cddfSDavid du Colombier 	FSM_use *u, *v, *w;
3697dd7cddfSDavid du Colombier 	int n;
3707dd7cddfSDavid du Colombier 
371*de2caf28SDavid du Colombier 	for (f = fsmx; f; f = f->nxt)		/* all states */
3727dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)		/* all edges */
3737dd7cddfSDavid du Colombier 	for (n = 0; n < 2; n++)			/* reads and writes */
3747dd7cddfSDavid du Colombier 	for (u = t->Val[n]; u; u = u->nxt)
3757dd7cddfSDavid du Colombier 	{	if (!u->var->context	/* global */
3767dd7cddfSDavid du Colombier 		||   u->var->type == CHAN
3777dd7cddfSDavid du Colombier 		||   u->var->type == STRUCT)
3787dd7cddfSDavid du Colombier 			continue;
3797dd7cddfSDavid du Colombier 		new_dfs();
3807dd7cddfSDavid du Colombier 		if (FSM_DFS(t->to, u))	/* cannot hit read before hitting write */
3817dd7cddfSDavid du Colombier 			u->special = n+1;	/* means, reset to 0 after use */
3827dd7cddfSDavid du Colombier 	}
3837dd7cddfSDavid du Colombier 
384312a1df1SDavid du Colombier 	if (!export_ast)
385*de2caf28SDavid du Colombier 	for (f = fsmx; f; f = f->nxt)
3867dd7cddfSDavid du Colombier 	for (t = f->t; t; t = t->nxt)
3877dd7cddfSDavid du Colombier 	for (n = 0; n < 2; n++)
3887dd7cddfSDavid du Colombier 	for (u = t->Val[n], w = (FSM_use *) 0; u; )
3897dd7cddfSDavid du Colombier 	{	if (u->special)
3907dd7cddfSDavid du Colombier 		{	v = u->nxt;
3917dd7cddfSDavid du Colombier 			if (!w)			/* remove from list */
3927dd7cddfSDavid du Colombier 				t->Val[n] = v;
3937dd7cddfSDavid du Colombier 			else
3947dd7cddfSDavid du Colombier 				w->nxt = v;
395312a1df1SDavid du Colombier #if q
3967dd7cddfSDavid du Colombier 			if (verbose&32)
3977dd7cddfSDavid du Colombier 			{	printf("%s : %3d:  %d -> %d \t",
3987dd7cddfSDavid du Colombier 					t->step->n->fn->name,
3997dd7cddfSDavid du Colombier 					t->step->n->ln,
4007dd7cddfSDavid du Colombier 					f->from,
4017dd7cddfSDavid du Colombier 					t->to);
4027dd7cddfSDavid du Colombier 				comment(stdout, t->step->n, 0);
4037dd7cddfSDavid du Colombier 				printf("\t%c%d: %s\n", n==0?'R':'L',
4047dd7cddfSDavid du Colombier 					u->special, u->var->name);
4057dd7cddfSDavid du Colombier 			}
4067dd7cddfSDavid du Colombier #endif
4077dd7cddfSDavid du Colombier 			if (good_dead(t->step, u))
4087dd7cddfSDavid du Colombier 			{	u->nxt = t->step->dead;	/* insert into dead */
4097dd7cddfSDavid du Colombier 				t->step->dead = u;
4107dd7cddfSDavid du Colombier 			}
4117dd7cddfSDavid du Colombier 			u = v;
4127dd7cddfSDavid du Colombier 		} else
4137dd7cddfSDavid du Colombier 		{	w = u;
4147dd7cddfSDavid du Colombier 			u = u->nxt;
4157dd7cddfSDavid du Colombier 	}	}
4167dd7cddfSDavid du Colombier }
4177dd7cddfSDavid du Colombier 
418312a1df1SDavid du Colombier void
rel_use(FSM_use * u)4197dd7cddfSDavid du Colombier rel_use(FSM_use *u)
4207dd7cddfSDavid du Colombier {
4217dd7cddfSDavid du Colombier 	if (!u) return;
4227dd7cddfSDavid du Colombier 	rel_use(u->nxt);
4237dd7cddfSDavid du Colombier 	u->var = (Symbol *) 0;
4247dd7cddfSDavid du Colombier 	u->special = 0;
4257dd7cddfSDavid du Colombier 	u->nxt = use_free;
4267dd7cddfSDavid du Colombier 	use_free = u;
4277dd7cddfSDavid du Colombier }
4287dd7cddfSDavid du Colombier 
4297dd7cddfSDavid du Colombier static void
rel_trans(FSM_trans * t)4307dd7cddfSDavid du Colombier rel_trans(FSM_trans *t)
4317dd7cddfSDavid du Colombier {
4327dd7cddfSDavid du Colombier 	if (!t) return;
4337dd7cddfSDavid du Colombier 	rel_trans(t->nxt);
4347dd7cddfSDavid du Colombier 	rel_use(t->Val[0]);
4357dd7cddfSDavid du Colombier 	rel_use(t->Val[1]);
4367dd7cddfSDavid du Colombier 	t->Val[0] = t->Val[1] = (FSM_use *) 0;
4377dd7cddfSDavid du Colombier 	t->nxt = trans_free;
4387dd7cddfSDavid du Colombier 	trans_free = t;
4397dd7cddfSDavid du Colombier }
4407dd7cddfSDavid du Colombier 
4417dd7cddfSDavid du Colombier static void
rel_state(FSM_state * f)4427dd7cddfSDavid du Colombier rel_state(FSM_state *f)
4437dd7cddfSDavid du Colombier {
4447dd7cddfSDavid du Colombier 	if (!f) return;
4457dd7cddfSDavid du Colombier 	rel_state(f->nxt);
4467dd7cddfSDavid du Colombier 	rel_trans(f->t);
4477dd7cddfSDavid du Colombier 	f->t = (FSM_trans *) 0;
4487dd7cddfSDavid du Colombier 	f->nxt = fsm_free;
4497dd7cddfSDavid du Colombier 	fsm_free = f;
4507dd7cddfSDavid du Colombier }
4517dd7cddfSDavid du Colombier 
4527dd7cddfSDavid du Colombier static void
FSM_DEL(void)4537dd7cddfSDavid du Colombier FSM_DEL(void)
4547dd7cddfSDavid du Colombier {
455*de2caf28SDavid du Colombier 	rel_state(fsmx);
456*de2caf28SDavid du Colombier 	fsmx = (FSM_state *) 0;
4577dd7cddfSDavid du Colombier }
4587dd7cddfSDavid du Colombier 
4597dd7cddfSDavid du Colombier static FSM_state *
mkstate(int s)4607dd7cddfSDavid du Colombier mkstate(int s)
4617dd7cddfSDavid du Colombier {	FSM_state *f;
4627dd7cddfSDavid du Colombier 
4637dd7cddfSDavid du Colombier 	/* fsm_tbl isn't allocated yet */
464*de2caf28SDavid du Colombier 	for (f = fsmx; f; f = f->nxt)
4657dd7cddfSDavid du Colombier 		if (f->from == s)
4667dd7cddfSDavid du Colombier 			break;
4677dd7cddfSDavid du Colombier 	if (!f)
4687dd7cddfSDavid du Colombier 	{	if (fsm_free)
4697dd7cddfSDavid du Colombier 		{	f = fsm_free;
4707dd7cddfSDavid du Colombier 			memset(f, 0, sizeof(FSM_state));
4717dd7cddfSDavid du Colombier 			fsm_free = fsm_free->nxt;
4727dd7cddfSDavid du Colombier 		} else
4737dd7cddfSDavid du Colombier 			f = (FSM_state *) emalloc(sizeof(FSM_state));
4747dd7cddfSDavid du Colombier 		f->from = s;
4757dd7cddfSDavid du Colombier 		f->t = (FSM_trans *) 0;
476*de2caf28SDavid du Colombier 		f->nxt = fsmx;
477*de2caf28SDavid du Colombier 		fsmx = f;
4787dd7cddfSDavid du Colombier 		if (s > max_st_id)
4797dd7cddfSDavid du Colombier 			max_st_id = s;
4807dd7cddfSDavid du Colombier 	}
4817dd7cddfSDavid du Colombier 	return f;
4827dd7cddfSDavid du Colombier }
4837dd7cddfSDavid du Colombier 
484312a1df1SDavid du Colombier static FSM_trans *
get_trans(int to)485312a1df1SDavid du Colombier get_trans(int to)
486312a1df1SDavid du Colombier {	FSM_trans *t;
4877dd7cddfSDavid du Colombier 
4887dd7cddfSDavid du Colombier 	if (trans_free)
4897dd7cddfSDavid du Colombier 	{	t = trans_free;
4907dd7cddfSDavid du Colombier 		memset(t, 0, sizeof(FSM_trans));
4917dd7cddfSDavid du Colombier 		trans_free = trans_free->nxt;
4927dd7cddfSDavid du Colombier 	} else
4937dd7cddfSDavid du Colombier 		t = (FSM_trans *) emalloc(sizeof(FSM_trans));
494312a1df1SDavid du Colombier 
4957dd7cddfSDavid du Colombier 	t->to = to;
496312a1df1SDavid du Colombier 	return t;
497312a1df1SDavid du Colombier }
498312a1df1SDavid du Colombier 
499312a1df1SDavid du Colombier static void
FSM_EDGE(int from,int to,Element * e)500312a1df1SDavid du Colombier FSM_EDGE(int from, int to, Element *e)
501312a1df1SDavid du Colombier {	FSM_state *f;
502312a1df1SDavid du Colombier 	FSM_trans *t;
503312a1df1SDavid du Colombier 
504312a1df1SDavid du Colombier 	f = mkstate(from);	/* find it or else make it */
505312a1df1SDavid du Colombier 	t = get_trans(to);
506312a1df1SDavid du Colombier 
5077dd7cddfSDavid du Colombier 	t->step = e;
5087dd7cddfSDavid du Colombier 	t->nxt = f->t;
5097dd7cddfSDavid du Colombier 	f->t = t;
5107dd7cddfSDavid du Colombier 
5117dd7cddfSDavid du Colombier 	f = mkstate(to);
5127dd7cddfSDavid du Colombier 	f->in++;
5137dd7cddfSDavid du Colombier 
514312a1df1SDavid du Colombier 	if (export_ast)
515312a1df1SDavid du Colombier 	{	t = get_trans(from);
516312a1df1SDavid du Colombier 		t->step = e;
517312a1df1SDavid du Colombier 		t->nxt = f->p;	/* from is a predecessor of to */
518312a1df1SDavid du Colombier 		f->p = t;
519312a1df1SDavid du Colombier 	}
520312a1df1SDavid du Colombier 
5217dd7cddfSDavid du Colombier 	if (t->step)
522*de2caf28SDavid du Colombier 	{	ana_stmnt(t, t->step->n, 0);
523*de2caf28SDavid du Colombier 	}
5247dd7cddfSDavid du Colombier }
5257dd7cddfSDavid du Colombier 
5267dd7cddfSDavid du Colombier #define LVAL	1
5277dd7cddfSDavid du Colombier #define RVAL	0
5287dd7cddfSDavid du Colombier 
5297dd7cddfSDavid du Colombier static void
ana_var(FSM_trans * t,Lextok * now,int usage)5307dd7cddfSDavid du Colombier ana_var(FSM_trans *t, Lextok *now, int usage)
5317dd7cddfSDavid du Colombier {	FSM_use *u, *v;
5327dd7cddfSDavid du Colombier 
533312a1df1SDavid du Colombier 	if (!t || !now || !now->sym)
534312a1df1SDavid du Colombier 		return;
535312a1df1SDavid du Colombier 
536312a1df1SDavid du Colombier 	if (now->sym->name[0] == '_'
537312a1df1SDavid du Colombier 	&&  (strcmp(now->sym->name, "_") == 0
538312a1df1SDavid du Colombier 	||   strcmp(now->sym->name, "_pid") == 0
539*de2caf28SDavid du Colombier 	||   strcmp(now->sym->name, "_priority") == 0
540312a1df1SDavid du Colombier 	||   strcmp(now->sym->name, "_last") == 0))
5417dd7cddfSDavid du Colombier 		return;
5427dd7cddfSDavid du Colombier 
5437dd7cddfSDavid du Colombier 	v = t->Val[usage];
5447dd7cddfSDavid du Colombier 	for (u = v; u; u = u->nxt)
5457dd7cddfSDavid du Colombier 		if (u->var == now->sym)
5467dd7cddfSDavid du Colombier 			return;	/* it's already there */
5477dd7cddfSDavid du Colombier 
5487dd7cddfSDavid du Colombier 	if (!now->lft)
5497dd7cddfSDavid du Colombier 	{	/* not for array vars -- it's hard to tell statically
5507dd7cddfSDavid du Colombier 		   if the index would, at runtime, evaluate to the
5517dd7cddfSDavid du Colombier 		   same values at lval and rval references
5527dd7cddfSDavid du Colombier 		*/
5537dd7cddfSDavid du Colombier 		if (use_free)
5547dd7cddfSDavid du Colombier 		{	u = use_free;
5557dd7cddfSDavid du Colombier 			use_free = use_free->nxt;
5567dd7cddfSDavid du Colombier 		} else
5577dd7cddfSDavid du Colombier 			u = (FSM_use *) emalloc(sizeof(FSM_use));
5587dd7cddfSDavid du Colombier 
5597dd7cddfSDavid du Colombier 		u->var = now->sym;
5607dd7cddfSDavid du Colombier 		u->nxt = t->Val[usage];
5617dd7cddfSDavid du Colombier 		t->Val[usage] = u;
5627dd7cddfSDavid du Colombier 	} else
5637dd7cddfSDavid du Colombier 		 ana_stmnt(t, now->lft, RVAL);	/* index */
5647dd7cddfSDavid du Colombier 
5657dd7cddfSDavid du Colombier 	if (now->sym->type == STRUCT
5667dd7cddfSDavid du Colombier 	&&  now->rgt
5677dd7cddfSDavid du Colombier 	&&  now->rgt->lft)
5687dd7cddfSDavid du Colombier 		ana_var(t, now->rgt->lft, usage);
5697dd7cddfSDavid du Colombier }
5707dd7cddfSDavid du Colombier 
5717dd7cddfSDavid du Colombier static void
ana_stmnt(FSM_trans * t,Lextok * now,int usage)5727dd7cddfSDavid du Colombier ana_stmnt(FSM_trans *t, Lextok *now, int usage)
5737dd7cddfSDavid du Colombier {	Lextok *v;
5747dd7cddfSDavid du Colombier 
5757dd7cddfSDavid du Colombier 	if (!t || !now) return;
5767dd7cddfSDavid du Colombier 
5777dd7cddfSDavid du Colombier 	switch (now->ntyp) {
5787dd7cddfSDavid du Colombier 	case '.':
5797dd7cddfSDavid du Colombier 	case BREAK:
5807dd7cddfSDavid du Colombier 	case GOTO:
5817dd7cddfSDavid du Colombier 	case CONST:
5827dd7cddfSDavid du Colombier 	case TIMEOUT:
5837dd7cddfSDavid du Colombier 	case NONPROGRESS:
5847dd7cddfSDavid du Colombier 	case  ELSE:
5857dd7cddfSDavid du Colombier 	case '@':
5867dd7cddfSDavid du Colombier 	case 'q':
5877dd7cddfSDavid du Colombier 	case IF:
5887dd7cddfSDavid du Colombier 	case DO:
5897dd7cddfSDavid du Colombier 	case ATOMIC:
5907dd7cddfSDavid du Colombier 	case NON_ATOMIC:
5917dd7cddfSDavid du Colombier 	case D_STEP:
592312a1df1SDavid du Colombier 	case C_CODE:
593312a1df1SDavid du Colombier 	case C_EXPR:
5947dd7cddfSDavid du Colombier 		break;
5957dd7cddfSDavid du Colombier 
596*de2caf28SDavid du Colombier 	case ',': /* reached with SET_P and array initializers */
597*de2caf28SDavid du Colombier 		if (now->lft && now->lft->rgt)
598*de2caf28SDavid du Colombier 		{	ana_stmnt(t, now->lft->rgt, RVAL);
599*de2caf28SDavid du Colombier 		}
600*de2caf28SDavid du Colombier 		break;
601*de2caf28SDavid du Colombier 
6027dd7cddfSDavid du Colombier 	case '!':
6037dd7cddfSDavid du Colombier 	case UMIN:
6047dd7cddfSDavid du Colombier 	case '~':
6057dd7cddfSDavid du Colombier 	case ENABLED:
606*de2caf28SDavid du Colombier 	case GET_P:
6077dd7cddfSDavid du Colombier 	case PC_VAL:
6087dd7cddfSDavid du Colombier 	case LEN:
6097dd7cddfSDavid du Colombier 	case FULL:
6107dd7cddfSDavid du Colombier 	case EMPTY:
6117dd7cddfSDavid du Colombier 	case NFULL:
6127dd7cddfSDavid du Colombier 	case NEMPTY:
6137dd7cddfSDavid du Colombier 	case ASSERT:
6147dd7cddfSDavid du Colombier 	case 'c':
6157dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
6167dd7cddfSDavid du Colombier 		break;
6177dd7cddfSDavid du Colombier 
618*de2caf28SDavid du Colombier 	case SET_P:
619*de2caf28SDavid du Colombier 		ana_stmnt(t, now->lft, RVAL); /* ',' */
620*de2caf28SDavid du Colombier 		ana_stmnt(t, now->lft->rgt, RVAL);
621*de2caf28SDavid du Colombier 		break;
622*de2caf28SDavid du Colombier 
6237dd7cddfSDavid du Colombier 	case '/':
6247dd7cddfSDavid du Colombier 	case '*':
6257dd7cddfSDavid du Colombier 	case '-':
6267dd7cddfSDavid du Colombier 	case '+':
6277dd7cddfSDavid du Colombier 	case '%':
6287dd7cddfSDavid du Colombier 	case '&':
6297dd7cddfSDavid du Colombier 	case '^':
6307dd7cddfSDavid du Colombier 	case '|':
6317dd7cddfSDavid du Colombier 	case LT:
6327dd7cddfSDavid du Colombier 	case GT:
6337dd7cddfSDavid du Colombier 	case LE:
6347dd7cddfSDavid du Colombier 	case GE:
6357dd7cddfSDavid du Colombier 	case NE:
6367dd7cddfSDavid du Colombier 	case EQ:
6377dd7cddfSDavid du Colombier 	case OR:
6387dd7cddfSDavid du Colombier 	case AND:
6397dd7cddfSDavid du Colombier 	case LSHIFT:
6407dd7cddfSDavid du Colombier 	case RSHIFT:
6417dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
6427dd7cddfSDavid du Colombier 		ana_stmnt(t, now->rgt, RVAL);
6437dd7cddfSDavid du Colombier 		break;
6447dd7cddfSDavid du Colombier 
6457dd7cddfSDavid du Colombier 	case ASGN:
646*de2caf28SDavid du Colombier 		if (check_track(now) == STRUCT) { break; }
647*de2caf28SDavid du Colombier 
6487dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, LVAL);
649*de2caf28SDavid du Colombier 		if (now->rgt->ntyp)
6507dd7cddfSDavid du Colombier 			ana_stmnt(t, now->rgt, RVAL);
6517dd7cddfSDavid du Colombier 		break;
6527dd7cddfSDavid du Colombier 
6537dd7cddfSDavid du Colombier 	case PRINT:
6547dd7cddfSDavid du Colombier 	case RUN:
6557dd7cddfSDavid du Colombier 		for (v = now->lft; v; v = v->rgt)
6567dd7cddfSDavid du Colombier 			ana_stmnt(t, v->lft, RVAL);
6577dd7cddfSDavid du Colombier 		break;
6587dd7cddfSDavid du Colombier 
659312a1df1SDavid du Colombier 	case PRINTM:
660312a1df1SDavid du Colombier 		if (now->lft && !now->lft->ismtyp)
661312a1df1SDavid du Colombier 			ana_stmnt(t, now->lft, RVAL);
662312a1df1SDavid du Colombier 		break;
663312a1df1SDavid du Colombier 
6647dd7cddfSDavid du Colombier 	case 's':
6657dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
6667dd7cddfSDavid du Colombier 		for (v = now->rgt; v; v = v->rgt)
6677dd7cddfSDavid du Colombier 			ana_stmnt(t, v->lft, RVAL);
6687dd7cddfSDavid du Colombier 		break;
6697dd7cddfSDavid du Colombier 
6707dd7cddfSDavid du Colombier 	case 'R':
6717dd7cddfSDavid du Colombier 	case 'r':
6727dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
6737dd7cddfSDavid du Colombier 		for (v = now->rgt; v; v = v->rgt)
6747dd7cddfSDavid du Colombier 		{	if (v->lft->ntyp == EVAL)
675*de2caf28SDavid du Colombier 			{	if (v->lft->lft->ntyp == ',')
676*de2caf28SDavid du Colombier 				{	ana_stmnt(t, v->lft->lft->lft, RVAL);
677*de2caf28SDavid du Colombier 				} else
678*de2caf28SDavid du Colombier 				{	ana_stmnt(t, v->lft->lft, RVAL);
6797dd7cddfSDavid du Colombier 				}
680*de2caf28SDavid du Colombier 			} else
681*de2caf28SDavid du Colombier 			{	if (v->lft->ntyp != CONST
682*de2caf28SDavid du Colombier 				&&  now->ntyp != 'R')		/* was v->lft->ntyp */
683*de2caf28SDavid du Colombier 				{	ana_stmnt(t, v->lft, LVAL);
684*de2caf28SDavid du Colombier 		}	}	}
6857dd7cddfSDavid du Colombier 		break;
6867dd7cddfSDavid du Colombier 
6877dd7cddfSDavid du Colombier 	case '?':
6887dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft, RVAL);
689312a1df1SDavid du Colombier 		if (now->rgt)
690312a1df1SDavid du Colombier 		{	ana_stmnt(t, now->rgt->lft, RVAL);
6917dd7cddfSDavid du Colombier 			ana_stmnt(t, now->rgt->rgt, RVAL);
692312a1df1SDavid du Colombier 		}
6937dd7cddfSDavid du Colombier 		break;
6947dd7cddfSDavid du Colombier 
6957dd7cddfSDavid du Colombier 	case NAME:
6967dd7cddfSDavid du Colombier 		ana_var(t, now, usage);
6977dd7cddfSDavid du Colombier 		break;
6987dd7cddfSDavid du Colombier 
6997dd7cddfSDavid du Colombier 	case   'p':	/* remote ref */
7007dd7cddfSDavid du Colombier 		ana_stmnt(t, now->lft->lft, RVAL);	/* process id */
7017dd7cddfSDavid du Colombier 		ana_var(t, now, RVAL);
7027dd7cddfSDavid du Colombier 		ana_var(t, now->rgt, RVAL);
7037dd7cddfSDavid du Colombier 		break;
7047dd7cddfSDavid du Colombier 
7057dd7cddfSDavid du Colombier 	default:
706*de2caf28SDavid du Colombier 		if (0) printf("spin: %s:%d, bad node type %d usage %d (ana_stmnt)\n",
707*de2caf28SDavid du Colombier 			now->fn->name, now->ln, now->ntyp, usage);
708*de2caf28SDavid du Colombier 		fatal("aborting (ana_stmnt)", (char *) 0);
7097dd7cddfSDavid du Colombier 	}
7107dd7cddfSDavid du Colombier }
7117dd7cddfSDavid du Colombier 
7127dd7cddfSDavid du Colombier void
ana_src(int dataflow,int merger)713312a1df1SDavid du Colombier ana_src(int dataflow, int merger)	/* called from main.c and guided.c */
7147dd7cddfSDavid du Colombier {	ProcList *p;
7157dd7cddfSDavid du Colombier 	Element *e;
716312a1df1SDavid du Colombier #if 0
7177dd7cddfSDavid du Colombier 	int counter = 1;
718312a1df1SDavid du Colombier #endif
719*de2caf28SDavid du Colombier 	for (p = ready; p; p = p->nxt)
72000d97012SDavid du Colombier 	{
7217dd7cddfSDavid du Colombier 		ana_seq(p->s);
7227dd7cddfSDavid du Colombier 		fsm_table();
7237dd7cddfSDavid du Colombier 
7247dd7cddfSDavid du Colombier 		e = p->s->frst;
7257dd7cddfSDavid du Colombier #if 0
7267dd7cddfSDavid du Colombier 		if (dataflow || merger)
7277dd7cddfSDavid du Colombier 		{	printf("spin: %d, optimizing '%s'",
7287dd7cddfSDavid du Colombier 				counter++, p->n->name);
7297dd7cddfSDavid du Colombier 			fflush(stdout);
7307dd7cddfSDavid du Colombier 		}
7317dd7cddfSDavid du Colombier #endif
7327dd7cddfSDavid du Colombier 		if (dataflow)
7337dd7cddfSDavid du Colombier 		{	FSM_ANA();
7347dd7cddfSDavid du Colombier 		}
7357dd7cddfSDavid du Colombier 		if (merger)
73600d97012SDavid du Colombier 		{	FSM_MERGER(/* p->n->name */);
737312a1df1SDavid du Colombier 			huntele(e, e->status, -1)->merge_in = 1; /* start-state */
7387dd7cddfSDavid du Colombier #if 0
7397dd7cddfSDavid du Colombier 			printf("\n");
7407dd7cddfSDavid du Colombier #endif
7417dd7cddfSDavid du Colombier 		}
742312a1df1SDavid du Colombier 		if (export_ast)
743312a1df1SDavid du Colombier 			AST_store(p, huntele(e, e->status, -1)->seqno);
744312a1df1SDavid du Colombier 
7457dd7cddfSDavid du Colombier 		FSM_DEL();
7467dd7cddfSDavid du Colombier 	}
7477dd7cddfSDavid du Colombier 	for (e = Al_El; e; e = e->Nxt)
7487dd7cddfSDavid du Colombier 	{
7497dd7cddfSDavid du Colombier 		if (!(e->status&DONE) && (verbose&32))
7507dd7cddfSDavid du Colombier 		{	printf("unreachable code: ");
75100d97012SDavid du Colombier 			printf("%s:%3d  ", e->n->fn->name, e->n->ln);
7527dd7cddfSDavid du Colombier 			comment(stdout, e->n, 0);
7537dd7cddfSDavid du Colombier 			printf("\n");
7547dd7cddfSDavid du Colombier 		}
7557dd7cddfSDavid du Colombier 		e->status &= ~DONE;
7567dd7cddfSDavid du Colombier 	}
757312a1df1SDavid du Colombier 	if (export_ast)
758312a1df1SDavid du Colombier 	{	AST_slice();
75900d97012SDavid du Colombier 		alldone(0);	/* changed in 5.3.0: was exit(0) */
760312a1df1SDavid du Colombier 	}
7617dd7cddfSDavid du Colombier }
7627dd7cddfSDavid du Colombier 
7637dd7cddfSDavid du Colombier void
spit_recvs(FILE * f1,FILE * f2)764312a1df1SDavid du Colombier spit_recvs(FILE *f1, FILE *f2)	/* called from pangen2.c */
7657dd7cddfSDavid du Colombier {	Element *e;
7667dd7cddfSDavid du Colombier 	Sequence *s;
7677dd7cddfSDavid du Colombier 	extern int Unique;
7687dd7cddfSDavid du Colombier 
7697dd7cddfSDavid du Colombier 	fprintf(f1, "unsigned char Is_Recv[%d];\n", Unique);
7707dd7cddfSDavid du Colombier 
7717dd7cddfSDavid du Colombier 	fprintf(f2, "void\nset_recvs(void)\n{\n");
7727dd7cddfSDavid du Colombier 	for (e = Al_El; e; e = e->Nxt)
7737dd7cddfSDavid du Colombier 	{	if (!e->n) continue;
7747dd7cddfSDavid du Colombier 
7757dd7cddfSDavid du Colombier 		switch (e->n->ntyp) {
7767dd7cddfSDavid du Colombier 		case 'r':
7777dd7cddfSDavid du Colombier markit:			fprintf(f2, "\tIs_Recv[%d] = 1;\n", e->Seqno);
7787dd7cddfSDavid du Colombier 			break;
7797dd7cddfSDavid du Colombier 		case D_STEP:
7807dd7cddfSDavid du Colombier 			s = e->n->sl->this;
7817dd7cddfSDavid du Colombier 			switch (s->frst->n->ntyp) {
7827dd7cddfSDavid du Colombier 			case DO:
7837dd7cddfSDavid du Colombier 				fatal("unexpected: do at start of d_step", (char *) 0);
7847dd7cddfSDavid du Colombier 			case IF: /* conservative: fall through */
7857dd7cddfSDavid du Colombier 			case 'r': goto markit;
7867dd7cddfSDavid du Colombier 			}
7877dd7cddfSDavid du Colombier 			break;
7887dd7cddfSDavid du Colombier 		}
7897dd7cddfSDavid du Colombier 	}
7907dd7cddfSDavid du Colombier 	fprintf(f2, "}\n");
7917dd7cddfSDavid du Colombier 
7927dd7cddfSDavid du Colombier 	if (rvopt)
7937dd7cddfSDavid du Colombier 	{
7947dd7cddfSDavid du Colombier 	fprintf(f2, "int\nno_recvs(int me)\n{\n");
7957dd7cddfSDavid du Colombier 	fprintf(f2, "	int h; uchar ot; short tt;\n");
7967dd7cddfSDavid du Colombier 	fprintf(f2, "	Trans *t;\n");
7977dd7cddfSDavid du Colombier 	fprintf(f2, "	for (h = BASE; h < (int) now._nr_pr; h++)\n");
7987dd7cddfSDavid du Colombier 	fprintf(f2, "	{	if (h == me) continue;\n");
7997dd7cddfSDavid du Colombier 	fprintf(f2, "		tt = (short) ((P0 *)pptr(h))->_p;\n");
8007dd7cddfSDavid du Colombier 	fprintf(f2, "		ot = (uchar) ((P0 *)pptr(h))->_t;\n");
8017dd7cddfSDavid du Colombier 	fprintf(f2, "		for (t = trans[ot][tt]; t; t = t->nxt)\n");
8027dd7cddfSDavid du Colombier 	fprintf(f2, "			if (Is_Recv[t->t_id]) return 0;\n");
8037dd7cddfSDavid du Colombier 	fprintf(f2, "	}\n");
8047dd7cddfSDavid du Colombier 	fprintf(f2, "	return 1;\n");
8057dd7cddfSDavid du Colombier 	fprintf(f2, "}\n");
8067dd7cddfSDavid du Colombier 	}
8077dd7cddfSDavid du Colombier }
8087dd7cddfSDavid du Colombier 
8097dd7cddfSDavid du Colombier static void
ana_seq(Sequence * s)8107dd7cddfSDavid du Colombier ana_seq(Sequence *s)
8117dd7cddfSDavid du Colombier {	SeqList *h;
8127dd7cddfSDavid du Colombier 	Sequence *t;
8137dd7cddfSDavid du Colombier 	Element *e, *g;
8147dd7cddfSDavid du Colombier 	int From, To;
8157dd7cddfSDavid du Colombier 
8167dd7cddfSDavid du Colombier 	for (e = s->frst; e; e = e->nxt)
8177dd7cddfSDavid du Colombier 	{	if (e->status & DONE)
8187dd7cddfSDavid du Colombier 			goto checklast;
8197dd7cddfSDavid du Colombier 
8207dd7cddfSDavid du Colombier 		e->status |= DONE;
8217dd7cddfSDavid du Colombier 
8227dd7cddfSDavid du Colombier 		From = e->seqno;
8237dd7cddfSDavid du Colombier 
8247dd7cddfSDavid du Colombier 		if (e->n->ntyp == UNLESS)
8257dd7cddfSDavid du Colombier 			ana_seq(e->sub->this);
8267dd7cddfSDavid du Colombier 		else if (e->sub)
8277dd7cddfSDavid du Colombier 		{	for (h = e->sub; h; h = h->nxt)
8287dd7cddfSDavid du Colombier 			{	g = huntstart(h->this->frst);
8297dd7cddfSDavid du Colombier 				To = g->seqno;
8307dd7cddfSDavid du Colombier 
8317dd7cddfSDavid du Colombier 				if (g->n->ntyp != 'c'
8327dd7cddfSDavid du Colombier 				||  g->n->lft->ntyp != CONST
8337dd7cddfSDavid du Colombier 				||  g->n->lft->val != 0
8347dd7cddfSDavid du Colombier 				||  g->esc)
8357dd7cddfSDavid du Colombier 					FSM_EDGE(From, To, e);
8367dd7cddfSDavid du Colombier 				/* else it's a dead link */
8377dd7cddfSDavid du Colombier 			}
8387dd7cddfSDavid du Colombier 			for (h = e->sub; h; h = h->nxt)
8397dd7cddfSDavid du Colombier 				ana_seq(h->this);
8407dd7cddfSDavid du Colombier 		} else if (e->n->ntyp == ATOMIC
8417dd7cddfSDavid du Colombier 			||  e->n->ntyp == D_STEP
8427dd7cddfSDavid du Colombier 			||  e->n->ntyp == NON_ATOMIC)
8437dd7cddfSDavid du Colombier 		{
8447dd7cddfSDavid du Colombier 			t = e->n->sl->this;
8457dd7cddfSDavid du Colombier 			g = huntstart(t->frst);
8467dd7cddfSDavid du Colombier 			t->last->nxt = e->nxt;
8477dd7cddfSDavid du Colombier 			To = g->seqno;
8487dd7cddfSDavid du Colombier 			FSM_EDGE(From, To, e);
8497dd7cddfSDavid du Colombier 
8507dd7cddfSDavid du Colombier 			ana_seq(t);
8517dd7cddfSDavid du Colombier 		} else
8527dd7cddfSDavid du Colombier 		{	if (e->n->ntyp == GOTO)
8537dd7cddfSDavid du Colombier 			{	g = get_lab(e->n, 1);
854312a1df1SDavid du Colombier 				g = huntele(g, e->status, -1);
855*de2caf28SDavid du Colombier 				if (!g)
856*de2caf28SDavid du Colombier 				{	fatal("unexpected error 2", (char *) 0);
857*de2caf28SDavid du Colombier 				}
8587dd7cddfSDavid du Colombier 				To = g->seqno;
8597dd7cddfSDavid du Colombier 			} else if (e->nxt)
860312a1df1SDavid du Colombier 			{	g = huntele(e->nxt, e->status, -1);
861*de2caf28SDavid du Colombier 				if (!g)
862*de2caf28SDavid du Colombier 				{	fatal("unexpected error 3", (char *) 0);
863*de2caf28SDavid du Colombier 				}
8647dd7cddfSDavid du Colombier 				To = g->seqno;
8657dd7cddfSDavid du Colombier 			} else
8667dd7cddfSDavid du Colombier 				To = 0;
8677dd7cddfSDavid du Colombier 
8687dd7cddfSDavid du Colombier 			FSM_EDGE(From, To, e);
8697dd7cddfSDavid du Colombier 
8707dd7cddfSDavid du Colombier 			if (e->esc
8717dd7cddfSDavid du Colombier 			&&  e->n->ntyp != GOTO
8727dd7cddfSDavid du Colombier 			&&  e->n->ntyp != '.')
8737dd7cddfSDavid du Colombier 			for (h = e->esc; h; h = h->nxt)
8747dd7cddfSDavid du Colombier 			{	g = huntstart(h->this->frst);
8757dd7cddfSDavid du Colombier 				To = g->seqno;
8767dd7cddfSDavid du Colombier 				FSM_EDGE(From, To, ZE);
8777dd7cddfSDavid du Colombier 				ana_seq(h->this);
8787dd7cddfSDavid du Colombier 			}
8797dd7cddfSDavid du Colombier 		}
8807dd7cddfSDavid du Colombier 
8817dd7cddfSDavid du Colombier checklast:	if (e == s->last)
8827dd7cddfSDavid du Colombier 			break;
8837dd7cddfSDavid du Colombier 	}
8847dd7cddfSDavid du Colombier }
885