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