📄 pangen6.c
字号:
/***** spin: pangen6.c *****//* Copyright (c) 2000-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 *//* Abstract syntax tree analysis / slicing (spin option -A) *//* AST_store stores the fsms's for each proctype *//* AST_track keeps track of variables used in properties *//* AST_slice starts the slicing algorithm *//* it first collects more info and then calls *//* AST_criteria to process the slice criteria */#include "spin.h"#ifdef PC#include "y_tab.h"#else#include "y.tab.h"#endifextern Ordered *all_names;extern FSM_use *use_free;extern FSM_state **fsm_tbl;extern FSM_state *fsm;extern int verbose, o_max;static FSM_trans *cur_t;static FSM_trans *expl_par;static FSM_trans *expl_var;static FSM_trans *explicit;extern void rel_use(FSM_use *);#define ulong unsigned longtypedef struct Pair { FSM_state *h; int b; struct Pair *nxt;} Pair;typedef struct AST { ProcList *p; /* proctype decl */ int i_st; /* start state */ int nstates, nwords; int relevant; Pair *pairs; /* entry and exit nodes of proper subgraphs */ FSM_state *fsm; /* proctype body */ struct AST *nxt; /* linked list */} AST;typedef struct RPN { /* relevant proctype names */ Symbol *rn; struct RPN *nxt;} RPN;typedef struct ALIAS { /* channel aliasing info */ Lextok *cnm; /* this chan */ int origin; /* debugging - origin of the alias */ struct ALIAS *alias; /* can be an alias for these other chans */ struct ALIAS *nxt; /* linked list */} ALIAS;typedef struct ChanList { Lextok *s; /* containing stmnt */ Lextok *n; /* point of reference - could be struct */ struct ChanList *nxt; /* linked list */} ChanList;/* a chan alias can be created in one of three ways: assignement to chan name a = b -- a is now an alias for b passing chan name as parameter in run run x(b) -- proctype x(chan a) passing chan name through channel x!b -- x?a */#define USE 1#define DEF 2#define DEREF_DEF 4#define DEREF_USE 8static AST *ast;static ALIAS *chalcur;static ALIAS *chalias;static ChanList *chanlist;static Slicer *slicer;static Slicer *rel_vars; /* all relevant variables */static int AST_Changes;static int AST_Round;static FSM_state no_state;static RPN *rpn;static int in_recv = 0;static int AST_mutual(Lextok *, Lextok *, int);static void AST_dominant(void);static void AST_hidden(void);static void AST_setcur(Lextok *);static void check_slice(Lextok *, int);static void curtail(AST *);static void def_use(Lextok *, int);static void name_AST_track(Lextok *, int);static void show_expl(void);static intAST_isini(Lextok *n) /* is this an initialized channel */{ Symbol *s; if (!n || !n->sym) return 0; s = n->sym; if (s->type == CHAN) return (s->ini->ntyp == CHAN); /* freshly instantiated */ if (s->type == STRUCT && n->rgt) return AST_isini(n->rgt->lft); return 0;}static voidAST_var(Lextok *n, Symbol *s, int toplevel){ if (!s) return; if (toplevel) { if (s->context && s->type) printf(":%s:L:", s->context->name); else printf("G:"); } printf("%s", s->name); /* array indices ignored */ if (s->type == STRUCT && n && n->rgt && n->rgt->lft) { printf(":"); AST_var(n->rgt->lft, n->rgt->lft->sym, 0); }}static voidname_def_indices(Lextok *n, int code){ if (!n || !n->sym) return; if (n->sym->nel != 1) def_use(n->lft, code); /* process the index */ if (n->sym->type == STRUCT /* and possible deeper ones */ && n->rgt) name_def_indices(n->rgt->lft, code);}static voidname_def_use(Lextok *n, int code){ FSM_use *u; if (!n) return; if ((code&USE) && cur_t->step && cur_t->step->n) { switch (cur_t->step->n->ntyp) { case 'c': /* possible predicate abstraction? */ n->sym->colnr |= 2; /* yes */ break; default: n->sym->colnr |= 1; /* no */ break; } } for (u = cur_t->Val[0]; u; u = u->nxt) if (AST_mutual(n, u->n, 1) && u->special == code) return; if (use_free) { u = use_free; use_free = use_free->nxt; } else u = (FSM_use *) emalloc(sizeof(FSM_use)); u->n = n; u->special = code; u->nxt = cur_t->Val[0]; cur_t->Val[0] = u; name_def_indices(n, USE|(code&(~DEF))); /* not def, but perhaps deref */}static voiddef_use(Lextok *now, int code){ Lextok *v; if (now) switch (now->ntyp) { case '!': case UMIN: case '~': case 'c': case ENABLED: case ASSERT: case EVAL: def_use(now->lft, USE|code); break; case LEN: case FULL: case EMPTY: case NFULL: case NEMPTY: def_use(now->lft, DEREF_USE|USE|code); break; case '/': case '*': case '-': case '+': case '%': case '&': case '^': case '|': case LE: case GE: case GT: case LT: case NE: case EQ: case OR: case AND: case LSHIFT: case RSHIFT: def_use(now->lft, USE|code); def_use(now->rgt, USE|code); break; case ASGN: def_use(now->lft, DEF|code); def_use(now->rgt, USE|code); break; case TYPE: /* name in parameter list */ name_def_use(now, code); break; case NAME: name_def_use(now, code); break; case RUN: name_def_use(now, USE); /* procname - not really needed */ for (v = now->lft; v; v = v->rgt) def_use(v->lft, USE); /* params */ break; case 's': def_use(now->lft, DEREF_DEF|DEREF_USE|USE|code); for (v = now->rgt; v; v = v->rgt) def_use(v->lft, USE|code); break; case 'r': def_use(now->lft, DEREF_DEF|DEREF_USE|USE|code); for (v = now->rgt; v; v = v->rgt) { if (v->lft->ntyp == EVAL) def_use(v->lft, code); /* will add USE */ else if (v->lft->ntyp != CONST) def_use(v->lft, DEF|code); } break; case 'R': def_use(now->lft, DEREF_USE|USE|code); for (v = now->rgt; v; v = v->rgt) { if (v->lft->ntyp == EVAL) def_use(v->lft, code); /* will add USE */ } break; case '?': def_use(now->lft, USE|code); if (now->rgt) { def_use(now->rgt->lft, code); def_use(now->rgt->rgt, code); } break; case PRINT: for (v = now->lft; v; v = v->rgt) def_use(v->lft, USE|code); break; case PRINTM: def_use(now->lft, USE); break; case CONST: case ELSE: /* ? */ case NONPROGRESS: case PC_VAL: case 'p': case 'q': break; case '.': case GOTO: case BREAK: case '@': case D_STEP: case ATOMIC: case NON_ATOMIC: case IF: case DO: case UNLESS: case TIMEOUT: case C_CODE: case C_EXPR: default: break; }}static intAST_add_alias(Lextok *n, int nr){ ALIAS *ca; int res; for (ca = chalcur->alias; ca; ca = ca->nxt) if (AST_mutual(ca->cnm, n, 1)) { res = (ca->origin&nr); ca->origin |= nr; /* 1, 2, or 4 - run, asgn, or rcv */ return (res == 0); /* 0 if already there with same origin */ } ca = (ALIAS *) emalloc(sizeof(ALIAS)); ca->cnm = n; ca->origin = nr; ca->nxt = chalcur->alias; chalcur->alias = ca; return 1;}static voidAST_run_alias(char *pn, char *s, Lextok *t, int parno){ Lextok *v; int cnt; if (!t) return; if (t->ntyp == RUN) { if (strcmp(t->sym->name, s) == 0) for (v = t->lft, cnt = 1; v; v = v->rgt, cnt++) if (cnt == parno) { AST_add_alias(v->lft, 1); /* RUN */ break; } } else { AST_run_alias(pn, s, t->lft, parno); AST_run_alias(pn, s, t->rgt, parno); }}static voidAST_findrun(char *s, int parno){ FSM_state *f; FSM_trans *t; AST *a; for (a = ast; a; a = a->nxt) /* automata */ for (f = a->fsm; f; f = f->nxt) /* control states */ for (t = f->t; t; t = t->nxt) /* transitions */ { if (t->step) AST_run_alias(a->p->n->name, s, t->step->n, parno); }}static voidAST_par_chans(ProcList *p) /* find local chan's init'd to chan passed as param */{ Ordered *walk; Symbol *sp; for (walk = all_names; walk; walk = walk->next) { sp = walk->entry; if (sp && sp->context && strcmp(sp->context->name, p->n->name) == 0 && sp->Nid >= 0 /* not itself a param */ && sp->type == CHAN && sp->ini->ntyp == NAME) /* != CONST and != CHAN */ { Lextok *x = nn(ZN, 0, ZN, ZN); x->sym = sp; AST_setcur(x); AST_add_alias(sp->ini, 2); /* ASGN */ } }}static voidAST_para(ProcList *p){ Lextok *f, *t, *c; int cnt = 0; AST_par_chans(p); for (f = p->p; f; f = f->rgt) /* list of types */ for (t = f->lft; t; t = t->rgt) { if (t->ntyp != ',') c = t; else c = t->lft; /* expanded struct */ cnt++; if (Sym_typ(c) == CHAN) { ALIAS *na = (ALIAS *) emalloc(sizeof(ALIAS)); na->cnm = c; na->nxt = chalias; chalcur = chalias = na;#if 0 printf("%s -- (par) -- ", p->n->name); AST_var(c, c->sym, 1); printf(" => <<");#endif AST_findrun(p->n->name, cnt);#if 0 printf(">>\n");#endif } }}static voidAST_haschan(Lextok *c){ if (!c) return; if (Sym_typ(c) == CHAN) { AST_add_alias(c, 2); /* ASGN */#if 0 printf("<<"); AST_var(c, c->sym, 1); printf(">>\n");#endif } else { AST_haschan(c->rgt); AST_haschan(c->lft); }}static intAST_nrpar(Lextok *n) /* 's' or 'r' */{ Lextok *m; int j = 0; for (m = n->rgt; m; m = m->rgt) j++; return j;}static intAST_ord(Lextok *n, Lextok *s){ Lextok *m; int j = 0; for (m = n->rgt; m; m = m->rgt) { j++; if (s->sym == m->lft->sym) return j; } return 0;}#if 0static voidAST_ownership(Symbol *s){ if (!s) return; printf("%s:", s->name); AST_ownership(s->owner);}#endifstatic intAST_mutual(Lextok *a, Lextok *b, int toplevel){ Symbol *as, *bs; if (!a && !b) return 1; if (!a || !b) return 0; as = a->sym; bs = b->sym; if (!as || !bs) return 0; if (toplevel && as->context != bs->context) return 0; if (as->type != bs->type) return 0; if (strcmp(as->name, bs->name) != 0) return 0; if (as->type == STRUCT && a && a->rgt && b && b->rgt) return AST_mutual(a->rgt->lft, b->rgt->lft, 0); return 1;}static voidAST_setcur(Lextok *n) /* set chalcur */{ ALIAS *ca; for (ca = chalias; ca; ca = ca->nxt) if (AST_mutual(ca->cnm, n, 1)) /* if same chan */ { chalcur = ca; return; } ca = (ALIAS *) emalloc(sizeof(ALIAS)); ca->cnm = n; ca->nxt = chalias; chalcur = chalias = ca;}static voidAST_other(AST *a) /* check chan params in asgns and recvs */{ FSM_state *f; FSM_trans *t; FSM_use *u; ChanList *cl; for (f = a->fsm; f; f = f->nxt) /* control states */ for (t = f->t; t; t = t->nxt) /* transitions */ for (u = t->Val[0]; u; u = u->nxt) /* def/use info */ if (Sym_typ(u->n) == CHAN && (u->special&DEF)) /* def of chan-name */ { AST_setcur(u->n); switch (t->step->n->ntyp) { case ASGN: AST_haschan(t->step->n->rgt); break; case 'r': /* guess sends where name may originate */ for (cl = chanlist; cl; cl = cl->nxt) /* all sends */ { int a = AST_nrpar(cl->s); int b = AST_nrpar(t->step->n); if (a != b) /* matching nrs of params */ continue; a = AST_ord(cl->s, cl->n); b = AST_ord(t->step->n, u->n); if (a != b) /* same position in parlist */ continue; AST_add_alias(cl->n, 4); /* RCV assume possible match */ } break; default: printf("type = %d\n", t->step->n->ntyp); non_fatal("unexpected chan def type", (char *) 0); break; } }}static voidAST_aliases(void){ ALIAS *na, *ca; for (na = chalias; na; na = na->nxt) { printf("\npossible aliases of "); AST_var(na->cnm, na->cnm->sym, 1); printf("\n\t"); for (ca = na->alias; ca; ca = ca->nxt) { if (!ca->cnm->sym) printf("no valid name "); else AST_var(ca->cnm, ca->cnm->sym, 1); printf("<"); if (ca->origin & 1) printf("RUN "); if (ca->origin & 2) printf("ASGN "); if (ca->origin & 4) printf("RCV "); printf("[%s]", AST_isini(ca->cnm)?"Initzd":"Name");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -