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