xref: /plan9-contrib/sys/src/cmd/spin/pangen4.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
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 					{	if (v->lft->lft->ntyp == ',')
101 						{	undostmnt(v->lft->lft->lft, m);
102 						} else
103 						{	undostmnt(v->lft->lft, m);
104 						}
105 					} else
106 					{	undostmnt(v->lft, m);
107 					}
108 					fprintf(fd_tb, ", %d);\n\t\t", (i==0)?1:0);
109 					break;
110 				default:
111 					fprintf(fd_tb, "unrecv");
112 					putname(fd_tb, "(", now->lft, m, ", XX-1, ");
113 					fprintf(fd_tb, "%d, ", i);
114 					if (v->lft->sym
115 					&& !strcmp(v->lft->sym->name, "_"))
116 					{	fprintf(fd_tb, "trpt->bup.oval");
117 						if (multi_oval > 0)
118 							fprintf(fd_tb, "s[%d]", jj);
119 					} else
120 						putstmnt(fd_tb, v->lft, m);
121 
122 					fprintf(fd_tb, ", %d);\n\t\t", (i==0)?1:0);
123 					if (multi_oval > 0)
124 						jj++;
125 					break;
126 			}	}
127 			jj = multi_oval - ii - 1;
128 
129 			if (now->val == 1 && multi_oval > 0)
130 				jj++;	/* new 3.4.0 */
131 
132 			for (v = now->rgt, i = 0; v; v = v->rgt, i++)
133 			{	switch(v->lft->ntyp) {
134 				case CONST:
135 				case EVAL:
136 					break;
137 				default:
138 					if (!v->lft->sym
139 					||  strcmp(v->lft->sym->name, "_") != 0)
140 					{	nocast=1; putstmnt(fd_tb, v->lft, m);
141 						nocast=0; fprintf(fd_tb, " = trpt->bup.oval");
142 						if (multi_oval > 0)
143 							fprintf(fd_tb, "s[%d]", jj);
144 						fprintf(fd_tb, ";\n\t\t");
145 					}
146 					if (multi_oval > 0)
147 						jj++;
148 					break;
149 			}	}
150 			multi_oval -= ii;
151 		}
152 		break;
153 
154 	case '@':
155 		fprintf(fd_tb, "p_restor(II);\n\t\t");
156 		break;
157 
158 	case SET_P:
159 		fprintf(fd_tb, "((P0 *)pptr((trpt->o_priority >> 8)))");
160 		fprintf(fd_tb, "->_priority = trpt->o_priority & 255");
161 		break;
162 
163 	case ASGN:
164 		if (check_track(now) == STRUCT) { break; }
165 
166 		nocast=1; putstmnt(fd_tb, now->lft, m);
167 		nocast=0; fprintf(fd_tb, " = trpt->bup.oval");
168 		if (multi_oval > 0)
169 		{	multi_oval--;
170 			fprintf(fd_tb, "s[%d]", multi_oval-1);
171 		}
172 		check_proc(now->rgt, m);
173 		break;
174 
175 	case 'c':
176 		check_proc(now->lft, m);
177 		break;
178 
179 	case '.':
180 	case GOTO:
181 	case ELSE:
182 	case BREAK:
183 		break;
184 
185 	case C_CODE:
186 		fprintf(fd_tb, "sv_restor();\n");
187 		break;
188 
189 	case ASSERT:
190 	case PRINT:
191 		check_proc(now, m);
192 		break;
193 	case PRINTM:
194 		break;
195 
196 	case ',':
197 		if (now->lft)	/* eval usertype5 */
198 		{	undostmnt(now->lft, m);
199 			break;
200 		} /* else fall thru */
201 	default:
202 		printf("spin: bad node type %d (.b)\n", now->ntyp);
203 		alldone(1);
204 	}
205 }
206 
207 int
any_undo(Lextok * now)208 any_undo(Lextok *now)
209 {	/* is there anything to undo on a return move? */
210 	if (!now) return 1;
211 	switch (now->ntyp) {
212 	case 'c':	return any_oper(now->lft, RUN);
213 	case ASSERT:
214 	case PRINT:	return any_oper(now, RUN);
215 
216 	case PRINTM:
217 	case   '.':
218 	case  GOTO:
219 	case  ELSE:
220 	case BREAK:	return 0;
221 	default:	return 1;
222 	}
223 }
224 
225 int
any_oper(Lextok * now,int oper)226 any_oper(Lextok *now, int oper)
227 {	/* check if an expression contains oper operator */
228 	if (!now) return 0;
229 	if (now->ntyp == oper)
230 		return 1;
231 	return (any_oper(now->lft, oper) || any_oper(now->rgt, oper));
232 }
233 
234 static void
check_proc(Lextok * now,int m)235 check_proc(Lextok *now, int m)
236 {
237 	if (!now)
238 		return;
239 	if (now->ntyp == '@' || now->ntyp == RUN)
240 	{	fprintf(fd_tb, ";\n\t\t");
241 		undostmnt(now, m);
242 	}
243 	check_proc(now->lft, m);
244 	check_proc(now->rgt, m);
245 }
246 
247 void
genunio(void)248 genunio(void)
249 {	char buf1[256];
250 	Queue *q; int i;
251 
252 	ntimes(fd_tc, 0, 1, R13_);
253 	for (q = qtab; q; q = q->nxt)
254 	{	fprintf(fd_tc, "\tcase %d:\n", q->qid);
255 
256 		if (has_sorted)
257 		{	sprintf(buf1, "((Q%d *)z)->contents", q->qid);
258 			fprintf(fd_tc, "#ifdef HAS_SORTED\n");
259 			fprintf(fd_tc, "\t\tj = trpt->ipt;\n");	/* ipt was bup.oval */
260 			fprintf(fd_tc, "#endif\n");
261 			fprintf(fd_tc, "\t\tfor (k = j; k < ((Q%d *)z)->Qlen; k++)\n",
262 				q->qid);
263 			fprintf(fd_tc, "\t\t{\n");
264 			for (i = 0; i < q->nflds; i++)
265 			fprintf(fd_tc, "\t\t\t%s[k].fld%d = %s[k+1].fld%d;\n",
266 				buf1, i, buf1, i);
267 			fprintf(fd_tc, "\t\t}\n");
268 			fprintf(fd_tc, "\t\tj = ((Q0 *)z)->Qlen;\n");
269 		}
270 
271 		sprintf(buf1, "((Q%d *)z)->contents[j].fld", q->qid);
272 		for (i = 0; i < q->nflds; i++)
273 			fprintf(fd_tc, "\t\t%s%d = 0;\n", buf1, i);
274 		if (q->nslots==0)
275 		{	/* check if rendezvous succeeded, 1 level down */
276 			fprintf(fd_tc, "\t\t_m = (trpt+1)->o_m;\n");
277 			fprintf(fd_tc, "\t\tif (_m) (trpt-1)->o_pm |= 1;\n");
278 			fprintf(fd_tc, "\t\tUnBlock;\n");
279 		} else
280 			fprintf(fd_tc, "\t\t_m = trpt->o_m;\n");
281 
282 		fprintf(fd_tc, "\t\tbreak;\n");
283 	}
284 	ntimes(fd_tc, 0, 1, R14_);
285 	for (q = qtab; q; q = q->nxt)
286 	{	sprintf(buf1, "((Q%d *)z)->contents", q->qid);
287 		fprintf(fd_tc, "	case %d:\n", q->qid);
288 		if (q->nslots == 0)
289 			fprintf(fd_tc, "\t\tif (strt) boq = from+1;\n");
290 		else if (q->nslots > 1)	/* shift */
291 		{	fprintf(fd_tc, "\t\tif (strt && slot<%d)\n",
292 							q->nslots-1);
293 			fprintf(fd_tc, "\t\t{\tfor (j--; j>=slot; j--)\n");
294 			fprintf(fd_tc, "\t\t\t{");
295 			for (i = 0; i < q->nflds; i++)
296 			{	fprintf(fd_tc, "\t%s[j+1].fld%d =\n\t\t\t",
297 							buf1, i);
298 				fprintf(fd_tc, "\t%s[j].fld%d;\n\t\t\t",
299 							buf1, i);
300 			}
301 			fprintf(fd_tc, "}\n\t\t}\n");
302 		}
303 		strcat(buf1, "[slot].fld");
304 		fprintf(fd_tc, "\t\tif (strt) {\n");
305 		for (i = 0; i < q->nflds; i++)
306 			fprintf(fd_tc, "\t\t\t%s%d = 0;\n", buf1, i);
307 		fprintf(fd_tc, "\t\t}\n");
308 		if (q->nflds == 1)	/* set */
309 			fprintf(fd_tc, "\t\tif (fld == 0) %s0 = fldvar;\n",
310 							buf1);
311 		else
312 		{	fprintf(fd_tc, "\t\tswitch (fld) {\n");
313 			for (i = 0; i < q->nflds; i++)
314 			{	fprintf(fd_tc, "\t\tcase %d:\t%s", i, buf1);
315 				fprintf(fd_tc, "%d = fldvar; break;\n", i);
316 			}
317 			fprintf(fd_tc, "\t\t}\n");
318 		}
319 		fprintf(fd_tc, "\t\tbreak;\n");
320 	}
321 	ntimes(fd_tc, 0, 1, R15_);
322 }
323 
324 extern void explain(int);
325 
326 int
proper_enabler(Lextok * n)327 proper_enabler(Lextok *n)
328 {
329 	if (!n) return 1;
330 	switch (n->ntyp) {
331 	case NEMPTY:	case FULL:
332 	case NFULL:	case EMPTY:
333 	case LEN:	case 'R':
334 	case NAME:
335 		has_provided = 1;
336 		if (strcmp(n->sym->name, "_pid") == 0
337 		||  strcmp(n->sym->name, "_priority") == 0)
338 			return 1;
339 		return (!(n->sym->context));
340 
341 	case C_EXPR:
342 	case CONST:
343 	case TIMEOUT:
344 		has_provided = 1;
345 		return 1;
346 
347 	case ENABLED:	case PC_VAL:
348 	case GET_P:	/* not SET_P */
349 		return proper_enabler(n->lft);
350 
351 	case '!': case UMIN: case '~':
352 		return proper_enabler(n->lft);
353 
354 	case '/': case '*': case '-': case '+':
355 	case '%': case LT:  case GT: case '&': case '^':
356 	case '|': case LE:  case GE:  case NE: case '?':
357 	case EQ:  case OR:  case AND: case LSHIFT:
358 	case RSHIFT: case 'c': /* case ',': */
359 		return proper_enabler(n->lft) && proper_enabler(n->rgt);
360 
361 	default:
362 		break;
363 	}
364 	printf("spin: saw ");
365 	explain(n->ntyp);
366 	printf("\n");
367 	return 0;
368 }
369