dstep.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /***** spin: dstep.c *****/
  10. /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
  11. /* All Rights Reserved. This software is for educational purposes only. */
  12. /* No guarantee whatsoever is expressed or implied by the distribution of */
  13. /* this code. Permission is given to distribute this code provided that */
  14. /* this introductory message is not removed and no monies are exchanged. */
  15. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  16. /* http://spinroot.com/ */
  17. /* Send all bug-reports and/or questions to: bugs@spinroot.com */
  18. #include "spin.h"
  19. #include "y.tab.h"
  20. #define MAXDSTEP 2048 /* was 512 */
  21. char *NextLab[64];
  22. int Level=0, GenCode=0, IsGuard=0, TestOnly=0;
  23. static int Tj=0, Jt=0, LastGoto=0;
  24. static int Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
  25. static void putCode(FILE *, Element *, Element *, Element *, int);
  26. extern int Pid, separate, OkBreak;
  27. static void
  28. Sourced(int n, int special)
  29. { int i;
  30. for (i = 0; i < Tj; i++)
  31. if (Tojump[i] == n)
  32. return;
  33. if (Tj >= MAXDSTEP)
  34. fatal("d_step sequence too long", (char *)0);
  35. Special[Tj] = special;
  36. Tojump[Tj++] = n;
  37. }
  38. static void
  39. Dested(int n)
  40. { int i;
  41. for (i = 0; i < Tj; i++)
  42. if (Tojump[i] == n)
  43. return;
  44. for (i = 0; i < Jt; i++)
  45. if (Jumpto[i] == n)
  46. return;
  47. if (Jt >= MAXDSTEP)
  48. fatal("d_step sequence too long", (char *)0);
  49. Jumpto[Jt++] = n;
  50. LastGoto = 1;
  51. }
  52. static void
  53. Mopup(FILE *fd)
  54. { int i, j;
  55. for (i = 0; i < Jt; i++)
  56. { for (j = 0; j < Tj; j++)
  57. if (Tojump[j] == Jumpto[i])
  58. break;
  59. if (j == Tj)
  60. { char buf[16];
  61. if (Jumpto[i] == OkBreak)
  62. { if (!LastGoto)
  63. fprintf(fd, "S_%.3d_0: /* break-dest */\n",
  64. OkBreak);
  65. } else {
  66. sprintf(buf, "S_%.3d_0", Jumpto[i]);
  67. non_fatal("goto %s breaks from d_step seq", buf);
  68. } } }
  69. for (j = 0; j < Tj; j++)
  70. { for (i = 0; i < Jt; i++)
  71. if (Tojump[j] == Jumpto[i])
  72. break;
  73. #ifdef DEBUG
  74. if (i == Jt && !Special[i])
  75. fprintf(fd, "\t\t/* no goto's to S_%.3d_0 */\n",
  76. Tojump[j]);
  77. #endif
  78. }
  79. for (j = i = 0; j < Tj; j++)
  80. if (Special[j])
  81. { Tojump[i] = Tojump[j];
  82. Special[i] = 2;
  83. if (i >= MAXDSTEP)
  84. fatal("cannot happen (dstep.c)", (char *)0);
  85. i++;
  86. }
  87. Tj = i; /* keep only the global exit-labels */
  88. Jt = 0;
  89. }
  90. static int
  91. FirstTime(int n)
  92. { int i;
  93. for (i = 0; i < Tj; i++)
  94. if (Tojump[i] == n)
  95. return (Special[i] <= 1);
  96. return 1;
  97. }
  98. static void
  99. illegal(Element *e, char *str)
  100. {
  101. printf("illegal operator in 'd_step:' '");
  102. comment(stdout, e->n, 0);
  103. printf("'\n");
  104. fatal("'%s'", str);
  105. }
  106. static void
  107. filterbad(Element *e)
  108. {
  109. switch (e->n->ntyp) {
  110. case ASSERT:
  111. case PRINT:
  112. case 'c':
  113. /* run cannot be completely undone
  114. * with sv_save-sv_restor
  115. */
  116. if (any_oper(e->n->lft, RUN))
  117. illegal(e, "run operator in d_step");
  118. /* remote refs inside d_step sequences
  119. * would be okay, but they cannot always
  120. * be interpreted by the simulator the
  121. * same as by the verifier (e.g., for an
  122. * error trail)
  123. */
  124. if (any_oper(e->n->lft, 'p'))
  125. illegal(e, "remote reference in d_step");
  126. break;
  127. case '@':
  128. illegal(e, "process termination");
  129. break;
  130. case D_STEP:
  131. illegal(e, "nested d_step sequence");
  132. break;
  133. case ATOMIC:
  134. illegal(e, "nested atomic sequence");
  135. break;
  136. default:
  137. break;
  138. }
  139. }
  140. static int
  141. CollectGuards(FILE *fd, Element *e, int inh)
  142. { SeqList *h; Element *ee;
  143. for (h = e->sub; h; h = h->nxt)
  144. { ee = huntstart(h->this->frst);
  145. filterbad(ee);
  146. switch (ee->n->ntyp) {
  147. case NON_ATOMIC:
  148. inh += CollectGuards(fd, ee->n->sl->this->frst, inh);
  149. break;
  150. case IF:
  151. inh += CollectGuards(fd, ee, inh);
  152. break;
  153. case '.':
  154. if (ee->nxt->n->ntyp == DO)
  155. inh += CollectGuards(fd, ee->nxt, inh);
  156. break;
  157. case ELSE:
  158. if (inh++ > 0) fprintf(fd, " || ");
  159. /* 4.2.5 */ if (!pid_is_claim(Pid))
  160. fprintf(fd, "(boq == -1 /* else */)");
  161. else
  162. fprintf(fd, "(1 /* else */)");
  163. break;
  164. case 'R':
  165. if (inh++ > 0) fprintf(fd, " || ");
  166. fprintf(fd, "("); TestOnly=1;
  167. putstmnt(fd, ee->n, ee->seqno);
  168. fprintf(fd, ")"); TestOnly=0;
  169. break;
  170. case 'r':
  171. if (inh++ > 0) fprintf(fd, " || ");
  172. fprintf(fd, "("); TestOnly=1;
  173. putstmnt(fd, ee->n, ee->seqno);
  174. fprintf(fd, ")"); TestOnly=0;
  175. break;
  176. case 's':
  177. if (inh++ > 0) fprintf(fd, " || ");
  178. fprintf(fd, "("); TestOnly=1;
  179. /* 4.2.1 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq == -1) && ");
  180. putstmnt(fd, ee->n, ee->seqno);
  181. fprintf(fd, ")"); TestOnly=0;
  182. break;
  183. case 'c':
  184. if (inh++ > 0) fprintf(fd, " || ");
  185. fprintf(fd, "("); TestOnly=1;
  186. if (!pid_is_claim(Pid))
  187. fprintf(fd, "(boq == -1 && ");
  188. putstmnt(fd, ee->n->lft, e->seqno);
  189. if (!pid_is_claim(Pid))
  190. fprintf(fd, ")");
  191. fprintf(fd, ")"); TestOnly=0;
  192. break;
  193. } }
  194. return inh;
  195. }
  196. int
  197. putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln, int seqno)
  198. { int isg=0; char buf[64];
  199. NextLab[0] = "continue";
  200. filterbad(s->frst);
  201. switch (s->frst->n->ntyp) {
  202. case UNLESS:
  203. non_fatal("'unless' inside d_step - ignored", (char *) 0);
  204. return putcode(fd, s->frst->n->sl->this, nxt, 0, ln, seqno);
  205. case NON_ATOMIC:
  206. (void) putcode(fd, s->frst->n->sl->this, ZE, 1, ln, seqno);
  207. break;
  208. case IF:
  209. fprintf(fd, "if (!(");
  210. if (!CollectGuards(fd, s->frst, 0)) /* what about boq? */
  211. fprintf(fd, "1");
  212. fprintf(fd, "))\n\t\t\tcontinue;");
  213. isg = 1;
  214. break;
  215. case '.':
  216. if (s->frst->nxt->n->ntyp == DO)
  217. { fprintf(fd, "if (!(");
  218. if (!CollectGuards(fd, s->frst->nxt, 0))
  219. fprintf(fd, "1");
  220. fprintf(fd, "))\n\t\t\tcontinue;");
  221. isg = 1;
  222. }
  223. break;
  224. case 'R': /* <- can't really happen (it's part of a 'c') */
  225. fprintf(fd, "if (!("); TestOnly=1;
  226. putstmnt(fd, s->frst->n, s->frst->seqno);
  227. fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
  228. break;
  229. case 'r':
  230. fprintf(fd, "if (!("); TestOnly=1;
  231. putstmnt(fd, s->frst->n, s->frst->seqno);
  232. fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
  233. break;
  234. case 's':
  235. fprintf(fd, "if (");
  236. #if 1
  237. /* 4.2.1 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq != -1) || ");
  238. #endif
  239. fprintf(fd, "!("); TestOnly=1;
  240. putstmnt(fd, s->frst->n, s->frst->seqno);
  241. fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
  242. break;
  243. case 'c':
  244. fprintf(fd, "if (!(");
  245. if (!pid_is_claim(Pid)) fprintf(fd, "boq == -1 && ");
  246. TestOnly=1;
  247. putstmnt(fd, s->frst->n->lft, s->frst->seqno);
  248. fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
  249. break;
  250. case ELSE:
  251. fprintf(fd, "if (boq != -1 || (");
  252. if (separate != 2) fprintf(fd, "trpt->");
  253. fprintf(fd, "o_pm&1))\n\t\t\tcontinue;");
  254. break;
  255. case ASGN: /* new 3.0.8 */
  256. fprintf(fd, "IfNotBlocked");
  257. break;
  258. }
  259. if (justguards) return 0;
  260. fprintf(fd, "\n\t\tsv_save();\n\t\t");
  261. #if 1
  262. fprintf(fd, "reached[%d][%d] = 1;\n\t\t", Pid, seqno);
  263. fprintf(fd, "reached[%d][t->st] = 1;\n\t\t", Pid); /* true next state */
  264. fprintf(fd, "reached[%d][tt] = 1;\n", Pid); /* true current state */
  265. #endif
  266. sprintf(buf, "Uerror(\"block in d_step seq, line %d\")", ln);
  267. NextLab[0] = buf;
  268. putCode(fd, s->frst, s->extent, nxt, isg);
  269. if (nxt)
  270. { extern Symbol *Fname;
  271. extern int lineno;
  272. if (FirstTime(nxt->Seqno)
  273. && (!(nxt->status & DONE2) || !(nxt->status & D_ATOM)))
  274. { fprintf(fd, "S_%.3d_0: /* 1 */\n", nxt->Seqno);
  275. nxt->status |= DONE2;
  276. LastGoto = 0;
  277. }
  278. Sourced(nxt->Seqno, 1);
  279. lineno = ln;
  280. Fname = nxt->n->fn;
  281. Mopup(fd);
  282. }
  283. unskip(s->frst->seqno);
  284. return LastGoto;
  285. }
  286. static void
  287. putCode(FILE *fd, Element *f, Element *last, Element *next, int isguard)
  288. { Element *e, *N;
  289. SeqList *h; int i;
  290. char NextOpt[64];
  291. static int bno = 0;
  292. for (e = f; e; e = e->nxt)
  293. { if (e->status & DONE2)
  294. continue;
  295. e->status |= DONE2;
  296. if (!(e->status & D_ATOM))
  297. { if (!LastGoto)
  298. { fprintf(fd, "\t\tgoto S_%.3d_0;\n",
  299. e->Seqno);
  300. Dested(e->Seqno);
  301. }
  302. break;
  303. }
  304. fprintf(fd, "S_%.3d_0: /* 2 */\n", e->Seqno);
  305. LastGoto = 0;
  306. Sourced(e->Seqno, 0);
  307. if (!e->sub)
  308. { filterbad(e);
  309. switch (e->n->ntyp) {
  310. case NON_ATOMIC:
  311. h = e->n->sl;
  312. putCode(fd, h->this->frst,
  313. h->this->extent, e->nxt, 0);
  314. break;
  315. case BREAK:
  316. if (LastGoto) break;
  317. if (e->nxt)
  318. { i = target( huntele(e->nxt,
  319. e->status, -1))->Seqno;
  320. fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
  321. fprintf(fd, "/* 'break' */\n");
  322. Dested(i);
  323. } else
  324. { if (next)
  325. { fprintf(fd, "\t\tgoto S_%.3d_0;",
  326. next->Seqno);
  327. fprintf(fd, " /* NEXT */\n");
  328. Dested(next->Seqno);
  329. } else
  330. fatal("cannot interpret d_step", 0);
  331. }
  332. break;
  333. case GOTO:
  334. if (LastGoto) break;
  335. i = huntele( get_lab(e->n,1),
  336. e->status, -1)->Seqno;
  337. fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
  338. fprintf(fd, "/* 'goto' */\n");
  339. Dested(i);
  340. break;
  341. case '.':
  342. if (LastGoto) break;
  343. if (e->nxt && (e->nxt->status & DONE2))
  344. { i = e->nxt?e->nxt->Seqno:0;
  345. fprintf(fd, "\t\tgoto S_%.3d_0;", i);
  346. fprintf(fd, " /* '.' */\n");
  347. Dested(i);
  348. }
  349. break;
  350. default:
  351. putskip(e->seqno);
  352. GenCode = 1; IsGuard = isguard;
  353. fprintf(fd, "\t\t");
  354. putstmnt(fd, e->n, e->seqno);
  355. fprintf(fd, ";\n");
  356. GenCode = IsGuard = isguard = LastGoto = 0;
  357. break;
  358. }
  359. i = e->nxt?e->nxt->Seqno:0;
  360. if (e->nxt && e->nxt->status & DONE2 && !LastGoto)
  361. { fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
  362. fprintf(fd, "/* ';' */\n");
  363. Dested(i);
  364. break;
  365. }
  366. } else
  367. { for (h = e->sub, i=1; h; h = h->nxt, i++)
  368. { sprintf(NextOpt, "goto S_%.3d_%d",
  369. e->Seqno, i);
  370. NextLab[++Level] = NextOpt;
  371. N = (e->n && e->n->ntyp == DO) ? e : e->nxt;
  372. putCode(fd, h->this->frst,
  373. h->this->extent, N, 1);
  374. Level--;
  375. fprintf(fd, "%s: /* 3 */\n", &NextOpt[5]);
  376. LastGoto = 0;
  377. }
  378. if (!LastGoto)
  379. { fprintf(fd, "\t\tUerror(\"blocking sel ");
  380. fprintf(fd, "in d_step (nr.%d, near line %d)\");\n",
  381. bno++, (e->n)?e->n->ln:0);
  382. LastGoto = 0;
  383. }
  384. }
  385. if (e == last)
  386. { if (!LastGoto && next)
  387. { fprintf(fd, "\t\tgoto S_%.3d_0;\n",
  388. next->Seqno);
  389. Dested(next->Seqno);
  390. }
  391. break;
  392. } }
  393. }