1 /***** spin: pangen4.c *****/
2 
3 /*
4  * This file is part of the public release of Spin. It is subject to the
5  * terms in the LICENSE file that is included in this source directory.
6  * Tool documentation is available at http://spinroot.com
7  */
8 
9 #include "spin.h"
10 #include "y.tab.h"
11 
12 extern FILE	*fd_tc, *fd_tb;
13 extern Queue	*qtab;
14 extern Symbol	*Fname;
15 extern int	lineno, m_loss, Pid_nr, eventmapnr, multi_oval;
16 extern short	nocast, has_provided, has_sorted;
17 extern const char *R13_[], *R14_[], *R15_[];
18 
19 static void	check_proc(Lextok *, int);
20 
21 void
undostmnt(Lextok * now,int m)22 undostmnt(Lextok *now, int m)
23 {	Lextok *v;
24 	int i, j;
25 
26 	if (!now)
27 	{	fprintf(fd_tb, "0");
28 		return;
29 	}
30 	lineno = now->ln;
31 	Fname  = now->fn;
32 	switch (now->ntyp) {
33 	case CONST:	case '!':	case UMIN:
34 	case '~':	case '/':	case '*':
35 	case '-':	case '+':	case '%':
36 	case LT:	case GT:	case '&':
37 	case '|':	case LE:	case GE:
38 	case NE:	case EQ:	case OR:
39 	case AND:	case LSHIFT:	case RSHIFT:
40 	case TIMEOUT:	case LEN:	case NAME:
41 	case FULL:	case EMPTY:	case 'R':
42 	case NFULL:	case NEMPTY:	case ENABLED:
43 	case '?':	case PC_VAL:	case '^':
44 	case C_EXPR:	case GET_P:
45 	case NONPROGRESS:
46 		putstmnt(fd_tb, now, m);
47 		break;
48 
49 	case RUN:
50 		fprintf(fd_tb, "delproc(0, now._nr_pr-1)");
51 		break;
52 
53 	case 's':
54 		if (Pid_nr == eventmapnr) break;
55 
56 		if (m_loss)
57 			fprintf(fd_tb, "if (_m == 2) ");
58 		putname(fd_tb, "_m = unsend(", now->lft, m, ")");
59 		break;
60 
61 	case 'r':
62 		if (Pid_nr == eventmapnr) break;
63 
64 		for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
65 			if (v->lft->ntyp != CONST
66 			&&  v->lft->ntyp != EVAL)
67 				j++;
68 		if (j == 0 && now->val >= 2)
69 			break;	/* poll without side-effect */
70 
71 		{	int ii = 0, jj;
72 
73 			for (v = now->rgt; v; v = v->rgt)
74 				if ((v->lft->ntyp != CONST
75 				&&   v->lft->ntyp != EVAL))
76 					ii++;	/* nr of things bupped */
77 			if (now->val == 1)
78 			{	ii++;
79 				jj = multi_oval - ii - 1;
80 				fprintf(fd_tb, "XX = trpt->bup.oval");
81 				if (multi_oval > 0)
82 				{	fprintf(fd_tb, "s[%d]", jj);
83 					jj++;
84 				}
85 				fprintf(fd_tb, ";\n\t\t");
86 			} else
87 			{	fprintf(fd_tb, "XX = 1;\n\t\t");
88 				jj = multi_oval - ii - 1;
89 			}
90 
91 			if (now->val < 2)	/* not for channel poll */
92 			for (v = now->rgt, i = 0; v; v = v->rgt, i++)
93 			{	switch(v->lft->ntyp) {
94 				case CONST:
95 				case EVAL:
96 					fprintf(fd_tb, "unrecv");
97 					putname(fd_tb, "(", now->lft, m, ", XX-1, ");
98 					fprintf(fd_tb, "%d, ", i);
99 					if (v->lft->ntyp == EVAL)
100 						undostmnt(v->lft->lft, m);
101 					else
102 						undostmnt(v->lft, m);
103 					fprintf(fd_tb, ", %d);\n\t\t", (i==0)?1:0);
104 					break;
105 				default:
106 					fprintf(fd_tb, "unrecv");
107 					putname(fd_tb, "(", now->lft, m, ", XX-1, ");
108 					fprintf(fd_tb, "%d, ", i);
109 					if (v->lft->sym
110 					&& !strcmp(v->lft->sym->name, "_"))
111 					{	fprintf(fd_tb, "trpt->bup.oval");
112 						if (multi_oval > 0)
113 							fprintf(fd_tb, "s[%d]", jj);
114 					} else
115 						putstmnt(fd_tb, v->lft, m);
116 
117 					fprintf(fd_tb, ", %d);\n\t\t", (i==0)?1:0);
118 					if (multi_oval > 0)
119 						jj++;
120 					break;
121 			}	}
122 			jj = multi_oval - ii - 1;
123 
124 			if (now->val == 1 && multi_oval > 0)
125 				jj++;	/* new 3.4.0 */
126 
127 			for (v = now->rgt, i = 0; v; v = v->rgt, i++)
128 			{	switch(v->lft->ntyp) {
129 				case CONST:
130 				case EVAL:
131 					break;
132 				default:
133 					if (!v->lft->sym
134 					||  strcmp(v->lft->sym->name, "_") != 0)
135 					{	nocast=1; putstmnt(fd_tb, v->lft, m);
136 						nocast=0; fprintf(fd_tb, " = trpt->bup.oval");
137 						if (multi_oval > 0)
138 							fprintf(fd_tb, "s[%d]", jj);
139 						fprintf(fd_tb, ";\n\t\t");
140 					}
141 					if (multi_oval > 0)
142 						jj++;
143 					break;
144 			}	}
145 			multi_oval -= ii;
146 		}
147 		break;
148 
149 	case '@':
150 		fprintf(fd_tb, "p_restor(II);\n\t\t");
151 		break;
152 
153 	case SET_P:
154 		fprintf(fd_tb, "((P0 *)pptr((trpt->o_priority >> 8)))");
155 		fprintf(fd_tb, "->_priority = trpt->o_priority & 255");
156 		break;
157 
158 	case ASGN:
159 		if (check_track(now) == STRUCT) { break; }
160 
161 		nocast=1; putstmnt(fd_tb, now->lft, m);
162 		nocast=0; fprintf(fd_tb, " = trpt->bup.oval");
163 		if (multi_oval > 0)
164 		{	multi_oval--;
165 			fprintf(fd_tb, "s[%d]", multi_oval-1);
166 		}
167 		check_proc(now->rgt, m);
168 		break;
169 
170 	case 'c':
171 		check_proc(now->lft, m);
172 		break;
173 
174 	case '.':
175 	case GOTO:
176 	case ELSE:
177 	case BREAK:
178 		break;
179 
180 	case C_CODE:
181 		fprintf(fd_tb, "sv_restor();\n");
182 		break;
183 
184 	case ASSERT:
185 	case PRINT:
186 		check_proc(now, m);
187 		break;
188 	case PRINTM:
189 		break;
190 
191 	default:
192 		printf("spin: bad node type %d (.b)\n", now->ntyp);
193 		alldone(1);
194 	}
195 }
196 
197 int
any_undo(Lextok * now)198 any_undo(Lextok *now)
199 {	/* is there anything to undo on a return move? */
200 	if (!now) return 1;
201 	switch (now->ntyp) {
202 	case 'c':	return any_oper(now->lft, RUN);
203 	case ASSERT:
204 	case PRINT:	return any_oper(now, RUN);
205 
206 	case PRINTM:
207 	case   '.':
208 	case  GOTO:
209 	case  ELSE:
210 	case BREAK:	return 0;
211 	default:	return 1;
212 	}
213 }
214 
215 int
any_oper(Lextok * now,int oper)216 any_oper(Lextok *now, int oper)
217 {	/* check if an expression contains oper operator */
218 	if (!now) return 0;
219 	if (now->ntyp == oper)
220 		return 1;
221 	return (any_oper(now->lft, oper) || any_oper(now->rgt, oper));
222 }
223 
224 static void
check_proc(Lextok * now,int m)225 check_proc(Lextok *now, int m)
226 {
227 	if (!now)
228 		return;
229 	if (now->ntyp == '@' || now->ntyp == RUN)
230 	{	fprintf(fd_tb, ";\n\t\t");
231 		undostmnt(now, m);
232 	}
233 	check_proc(now->lft, m);
234 	check_proc(now->rgt, m);
235 }
236 
237 void
genunio(void)238 genunio(void)
239 {	char buf1[256];
240 	Queue *q; int i;
241 
242 	ntimes(fd_tc, 0, 1, R13_);
243 	for (q = qtab; q; q = q->nxt)
244 	{	fprintf(fd_tc, "\tcase %d:\n", q->qid);
245 
246 		if (has_sorted)
247 		{	sprintf(buf1, "((Q%d *)z)->contents", q->qid);
248 			fprintf(fd_tc, "#ifdef HAS_SORTED\n");
249 			fprintf(fd_tc, "\t\tj = trpt->ipt;\n");	/* ipt was bup.oval */
250 			fprintf(fd_tc, "#endif\n");
251 			fprintf(fd_tc, "\t\tfor (k = j; k < ((Q%d *)z)->Qlen; k++)\n",
252 				q->qid);
253 			fprintf(fd_tc, "\t\t{\n");
254 			for (i = 0; i < q->nflds; i++)
255 			fprintf(fd_tc, "\t\t\t%s[k].fld%d = %s[k+1].fld%d;\n",
256 				buf1, i, buf1, i);
257 			fprintf(fd_tc, "\t\t}\n");
258 			fprintf(fd_tc, "\t\tj = ((Q0 *)z)->Qlen;\n");
259 		}
260 
261 		sprintf(buf1, "((Q%d *)z)->contents[j].fld", q->qid);
262 		for (i = 0; i < q->nflds; i++)
263 			fprintf(fd_tc, "\t\t%s%d = 0;\n", buf1, i);
264 		if (q->nslots==0)
265 		{	/* check if rendezvous succeeded, 1 level down */
266 			fprintf(fd_tc, "\t\t_m = (trpt+1)->o_m;\n");
267 			fprintf(fd_tc, "\t\tif (_m) (trpt-1)->o_pm |= 1;\n");
268 			fprintf(fd_tc, "\t\tUnBlock;\n");
269 		} else
270 			fprintf(fd_tc, "\t\t_m = trpt->o_m;\n");
271 
272 		fprintf(fd_tc, "\t\tbreak;\n");
273 	}
274 	ntimes(fd_tc, 0, 1, R14_);
275 	for (q = qtab; q; q = q->nxt)
276 	{	sprintf(buf1, "((Q%d *)z)->contents", q->qid);
277 		fprintf(fd_tc, "	case %d:\n", q->qid);
278 		if (q->nslots == 0)
279 			fprintf(fd_tc, "\t\tif (strt) boq = from+1;\n");
280 		else if (q->nslots > 1)	/* shift */
281 		{	fprintf(fd_tc, "\t\tif (strt && slot<%d)\n",
282 							q->nslots-1);
283 			fprintf(fd_tc, "\t\t{\tfor (j--; j>=slot; j--)\n");
284 			fprintf(fd_tc, "\t\t\t{");
285 			for (i = 0; i < q->nflds; i++)
286 			{	fprintf(fd_tc, "\t%s[j+1].fld%d =\n\t\t\t",
287 							buf1, i);
288 				fprintf(fd_tc, "\t%s[j].fld%d;\n\t\t\t",
289 							buf1, i);
290 			}
291 			fprintf(fd_tc, "}\n\t\t}\n");
292 		}
293 		strcat(buf1, "[slot].fld");
294 		fprintf(fd_tc, "\t\tif (strt) {\n");
295 		for (i = 0; i < q->nflds; i++)
296 			fprintf(fd_tc, "\t\t\t%s%d = 0;\n", buf1, i);
297 		fprintf(fd_tc, "\t\t}\n");
298 		if (q->nflds == 1)	/* set */
299 			fprintf(fd_tc, "\t\tif (fld == 0) %s0 = fldvar;\n",
300 							buf1);
301 		else
302 		{	fprintf(fd_tc, "\t\tswitch (fld) {\n");
303 			for (i = 0; i < q->nflds; i++)
304 			{	fprintf(fd_tc, "\t\tcase %d:\t%s", i, buf1);
305 				fprintf(fd_tc, "%d = fldvar; break;\n", i);
306 			}
307 			fprintf(fd_tc, "\t\t}\n");
308 		}
309 		fprintf(fd_tc, "\t\tbreak;\n");
310 	}
311 	ntimes(fd_tc, 0, 1, R15_);
312 }
313 
314 extern void explain(int);
315 
316 int
proper_enabler(Lextok * n)317 proper_enabler(Lextok *n)
318 {
319 	if (!n) return 1;
320 	switch (n->ntyp) {
321 	case NEMPTY:	case FULL:
322 	case NFULL:	case EMPTY:
323 	case LEN:	case 'R':
324 	case NAME:
325 		has_provided = 1;
326 		if (strcmp(n->sym->name, "_pid") == 0
327 		||  strcmp(n->sym->name, "_priority") == 0)
328 			return 1;
329 		return (!(n->sym->context));
330 
331 	case C_EXPR:
332 	case CONST:
333 	case TIMEOUT:
334 		has_provided = 1;
335 		return 1;
336 
337 	case ENABLED:	case PC_VAL:
338 	case GET_P:	/* not SET_P */
339 		return proper_enabler(n->lft);
340 
341 	case '!': case UMIN: case '~':
342 		return proper_enabler(n->lft);
343 
344 	case '/': case '*': case '-': case '+':
345 	case '%': case LT:  case GT: case '&': case '^':
346 	case '|': case LE:  case GE:  case NE: case '?':
347 	case EQ:  case OR:  case AND: case LSHIFT:
348 	case RSHIFT: case 'c': /* case ',': */
349 		return proper_enabler(n->lft) && proper_enabler(n->rgt);
350 
351 	default:
352 		break;
353 	}
354 	printf("spin: saw ");
355 	explain(n->ntyp);
356 	printf("\n");
357 	return 0;
358 }
359