diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/spin/pangen4.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/spin/pangen4.c')
-rwxr-xr-x | sys/src/cmd/spin/pangen4.c | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/sys/src/cmd/spin/pangen4.c b/sys/src/cmd/spin/pangen4.c new file mode 100755 index 000000000..777371fc7 --- /dev/null +++ b/sys/src/cmd/spin/pangen4.c @@ -0,0 +1,344 @@ +/***** spin: pangen4.c *****/ + +/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ +/* All Rights Reserved. This software is for educational purposes only. */ +/* No guarantee whatsoever is expressed or implied by the distribution of */ +/* this code. Permission is given to distribute this code provided that */ +/* this introductory message is not removed and no monies are exchanged. */ +/* Software written by Gerard J. Holzmann. For tool documentation see: */ +/* http://spinroot.com/ */ +/* Send all bug-reports and/or questions to: bugs@spinroot.com */ + +#include "spin.h" +#include "y.tab.h" + +extern FILE *tc, *tb; +extern Queue *qtab; +extern Symbol *Fname; +extern int lineno, m_loss, Pid, eventmapnr, multi_oval; +extern short nocast, has_provided, has_sorted; +extern char *R13[], *R14[], *R15[]; + +static void check_proc(Lextok *, int); + +void +undostmnt(Lextok *now, int m) +{ Lextok *v; + int i, j; + + if (!now) + { fprintf(tb, "0"); + return; + } + lineno = now->ln; + Fname = now->fn; + switch (now->ntyp) { + case CONST: case '!': case UMIN: + case '~': case '/': case '*': + case '-': case '+': case '%': + case LT: case GT: case '&': + case '|': case LE: case GE: + case NE: case EQ: case OR: + case AND: case LSHIFT: case RSHIFT: + case TIMEOUT: case LEN: case NAME: + case FULL: case EMPTY: case 'R': + case NFULL: case NEMPTY: case ENABLED: + case '?': case PC_VAL: case '^': + case C_EXPR: + case NONPROGRESS: + putstmnt(tb, now, m); + break; + + case RUN: + fprintf(tb, "delproc(0, now._nr_pr-1)"); + break; + + case 's': + if (Pid == eventmapnr) break; + + if (m_loss) + fprintf(tb, "if (_m == 2) "); + putname(tb, "_m = unsend(", now->lft, m, ")"); + break; + + case 'r': + if (Pid == eventmapnr) break; + + for (v = now->rgt, i=j=0; v; v = v->rgt, i++) + if (v->lft->ntyp != CONST + && v->lft->ntyp != EVAL) + j++; + if (j == 0 && now->val >= 2) + break; /* poll without side-effect */ + + { int ii = 0, jj; + + for (v = now->rgt; v; v = v->rgt) + if ((v->lft->ntyp != CONST + && v->lft->ntyp != EVAL)) + ii++; /* nr of things bupped */ + if (now->val == 1) + { ii++; + jj = multi_oval - ii - 1; + fprintf(tb, "XX = trpt->bup.oval"); + if (multi_oval > 0) + { fprintf(tb, "s[%d]", jj); + jj++; + } + fprintf(tb, ";\n\t\t"); + } else + { fprintf(tb, "XX = 1;\n\t\t"); + jj = multi_oval - ii - 1; + } + + if (now->val < 2) /* not for channel poll */ + for (v = now->rgt, i = 0; v; v = v->rgt, i++) + { switch(v->lft->ntyp) { + case CONST: + case EVAL: + fprintf(tb, "unrecv"); + putname(tb, "(", now->lft, m, ", XX-1, "); + fprintf(tb, "%d, ", i); + if (v->lft->ntyp == EVAL) + undostmnt(v->lft->lft, m); + else + undostmnt(v->lft, m); + fprintf(tb, ", %d);\n\t\t", (i==0)?1:0); + break; + default: + fprintf(tb, "unrecv"); + putname(tb, "(", now->lft, m, ", XX-1, "); + fprintf(tb, "%d, ", i); + if (v->lft->sym + && !strcmp(v->lft->sym->name, "_")) + { fprintf(tb, "trpt->bup.oval"); + if (multi_oval > 0) + fprintf(tb, "s[%d]", jj); + } else + putstmnt(tb, v->lft, m); + + fprintf(tb, ", %d);\n\t\t", (i==0)?1:0); + if (multi_oval > 0) + jj++; + break; + } } + jj = multi_oval - ii - 1; + + if (now->val == 1 && multi_oval > 0) + jj++; /* new 3.4.0 */ + + for (v = now->rgt, i = 0; v; v = v->rgt, i++) + { switch(v->lft->ntyp) { + case CONST: + case EVAL: + break; + default: + if (!v->lft->sym + || strcmp(v->lft->sym->name, "_") != 0) + { nocast=1; putstmnt(tb,v->lft,m); + nocast=0; fprintf(tb, " = trpt->bup.oval"); + if (multi_oval > 0) + fprintf(tb, "s[%d]", jj); + fprintf(tb, ";\n\t\t"); + } + if (multi_oval > 0) + jj++; + break; + } } + multi_oval -= ii; + } + break; + + case '@': + fprintf(tb, "p_restor(II);\n\t\t"); + break; + + case ASGN: + nocast=1; putstmnt(tb,now->lft,m); + nocast=0; fprintf(tb, " = trpt->bup.oval"); + if (multi_oval > 0) + { multi_oval--; + fprintf(tb, "s[%d]", multi_oval-1); + } + check_proc(now->rgt, m); + break; + + case 'c': + check_proc(now->lft, m); + break; + + case '.': + case GOTO: + case ELSE: + case BREAK: + break; + + case C_CODE: + fprintf(tb, "sv_restor();\n"); + break; + + case ASSERT: + case PRINT: + check_proc(now, m); + break; + case PRINTM: + break; + + default: + printf("spin: bad node type %d (.b)\n", now->ntyp); + alldone(1); + } +} + +int +any_undo(Lextok *now) +{ /* is there anything to undo on a return move? */ + if (!now) return 1; + switch (now->ntyp) { + case 'c': return any_oper(now->lft, RUN); + case ASSERT: + case PRINT: return any_oper(now, RUN); + + case PRINTM: + case '.': + case GOTO: + case ELSE: + case BREAK: return 0; + default: return 1; + } +} + +int +any_oper(Lextok *now, int oper) +{ /* check if an expression contains oper operator */ + if (!now) return 0; + if (now->ntyp == oper) + return 1; + return (any_oper(now->lft, oper) || any_oper(now->rgt, oper)); +} + +static void +check_proc(Lextok *now, int m) +{ + if (!now) + return; + if (now->ntyp == '@' || now->ntyp == RUN) + { fprintf(tb, ";\n\t\t"); + undostmnt(now, m); + } + check_proc(now->lft, m); + check_proc(now->rgt, m); +} + +void +genunio(void) +{ char buf1[256]; + Queue *q; int i; + + ntimes(tc, 0, 1, R13); + for (q = qtab; q; q = q->nxt) + { fprintf(tc, "\tcase %d:\n", q->qid); + + if (has_sorted) + { sprintf(buf1, "((Q%d *)z)->contents", q->qid); + fprintf(tc, "#ifdef HAS_SORTED\n"); + fprintf(tc, "\t\tj = trpt->ipt;\n"); /* ipt was bup.oval */ + fprintf(tc, "#endif\n"); + fprintf(tc, "\t\tfor (k = j; k < ((Q%d *)z)->Qlen; k++)\n", + q->qid); + fprintf(tc, "\t\t{\n"); + for (i = 0; i < q->nflds; i++) + fprintf(tc, "\t\t\t%s[k].fld%d = %s[k+1].fld%d;\n", + buf1, i, buf1, i); + fprintf(tc, "\t\t}\n"); + fprintf(tc, "\t\tj = ((Q0 *)z)->Qlen;\n"); + } + + sprintf(buf1, "((Q%d *)z)->contents[j].fld", q->qid); + for (i = 0; i < q->nflds; i++) + fprintf(tc, "\t\t%s%d = 0;\n", buf1, i); + if (q->nslots==0) + { /* check if rendezvous succeeded, 1 level down */ + fprintf(tc, "\t\t_m = (trpt+1)->o_m;\n"); + fprintf(tc, "\t\tif (_m) (trpt-1)->o_pm |= 1;\n"); + fprintf(tc, "\t\tUnBlock;\n"); + } else + fprintf(tc, "\t\t_m = trpt->o_m;\n"); + + fprintf(tc, "\t\tbreak;\n"); + } + ntimes(tc, 0, 1, R14); + for (q = qtab; q; q = q->nxt) + { sprintf(buf1, "((Q%d *)z)->contents", q->qid); + fprintf(tc, " case %d:\n", q->qid); + if (q->nslots == 0) + fprintf(tc, "\t\tif (strt) boq = from+1;\n"); + else if (q->nslots > 1) /* shift */ + { fprintf(tc, "\t\tif (strt && slot<%d)\n", + q->nslots-1); + fprintf(tc, "\t\t{\tfor (j--; j>=slot; j--)\n"); + fprintf(tc, "\t\t\t{"); + for (i = 0; i < q->nflds; i++) + { fprintf(tc, "\t%s[j+1].fld%d =\n\t\t\t", + buf1, i); + fprintf(tc, "\t%s[j].fld%d;\n\t\t\t", + buf1, i); + } + fprintf(tc, "}\n\t\t}\n"); + } + strcat(buf1, "[slot].fld"); + fprintf(tc, "\t\tif (strt) {\n"); + for (i = 0; i < q->nflds; i++) + fprintf(tc, "\t\t\t%s%d = 0;\n", buf1, i); + fprintf(tc, "\t\t}\n"); + if (q->nflds == 1) /* set */ + fprintf(tc, "\t\tif (fld == 0) %s0 = fldvar;\n", + buf1); + else + { fprintf(tc, "\t\tswitch (fld) {\n"); + for (i = 0; i < q->nflds; i++) + { fprintf(tc, "\t\tcase %d:\t%s", i, buf1); + fprintf(tc, "%d = fldvar; break;\n", i); + } + fprintf(tc, "\t\t}\n"); + } + fprintf(tc, "\t\tbreak;\n"); + } + ntimes(tc, 0, 1, R15); +} + +int +proper_enabler(Lextok *n) +{ + if (!n) return 1; + switch (n->ntyp) { + case NEMPTY: case FULL: + case NFULL: case EMPTY: + case LEN: case 'R': + case NAME: + has_provided = 1; + if (strcmp(n->sym->name, "_pid") == 0) + return 1; + return (!(n->sym->context)); + + case CONST: case TIMEOUT: + has_provided = 1; + return 1; + + case ENABLED: case PC_VAL: + return proper_enabler(n->lft); + + case '!': case UMIN: case '~': + return proper_enabler(n->lft); + + case '/': case '*': case '-': case '+': + case '%': case LT: case GT: case '&': case '^': + case '|': case LE: case GE: case NE: case '?': + case EQ: case OR: case AND: case LSHIFT: + case RSHIFT: case 'c': + return proper_enabler(n->lft) && proper_enabler(n->rgt); + default: + break; + } + return 0; +} |