int paste_blockoff(char *buf, unsigned int len, void *priv) { struct io_u *io = priv; unsigned long long off; typecheck(typeof(off), io->offset); off = cpu_to_le64((uint64_t)io->offset); len = min(len, (unsigned int)sizeof(off)); memcpy(buf, &off, len); return 0; }
int CodeRevision::compile() { if ( _status >= rev_COMPILED ) return 1; if ( !typecheck() ) return 0; //compilating //now have some bytecode to point to... _status = rev_COMPILED; fprintf (stderr, "rev- compiled\n"); setVersion(); return 1; }
static Node* typebsw(Case *c0, int ncase) { NodeList *cas; Node *a, *n; Case *c; int i, half; cas = nil; if(ncase < Ncase) { for(i=0; i<ncase; i++) { n = c0->node; if(c0->type != Ttypeconst) fatal("typebsw"); a = nod(OIF, N, N); a->ntest = nod(OEQ, hashname, nodintconst(c0->hash)); typecheck(&a->ntest, Erv); a->nbody = list1(n->right); cas = list(cas, a); c0 = c0->link; } return liststmt(cas); } // find the middle and recur c = c0; half = ncase>>1; for(i=1; i<half; i++) c = c->link; a = nod(OIF, N, N); a->ntest = nod(OLE, hashname, nodintconst(c->hash)); typecheck(&a->ntest, Erv); a->nbody = list1(typebsw(c0, half)); a->nelse = list1(typebsw(c->link, ncase-half)); return a; }
/* * find_and_open_tombstone - find an available tombstone slot, if any, of the * form tombstone_XX where XX is 00 to MAX_TOMBSTONES-1, inclusive. If no * file is available, we reuse the least-recently-modified file. */ static int find_and_open_tombstone(void) { unsigned long mtime = ULONG_MAX; struct stat sb; char path[128]; int fd, i, oldest = 0; /* * XXX: Our stat.st_mtime isn't time_t. If it changes, as it probably ought * to, our logic breaks. This check will generate a warning if that happens. */ typecheck(mtime, sb.st_mtime); /* * In a single wolf-like pass, find an available slot and, in case none * exist, find and record the least-recently-modified file. */ for (i = 0; i < MAX_TOMBSTONES; i++) { snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", i); if (!stat(path, &sb)) { if (sb.st_mtime < mtime) { oldest = i; mtime = sb.st_mtime; } continue; } if (errno != ENOENT) continue; fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0600); if (fd < 0) continue; /* raced ? */ fchown(fd, AID_SYSTEM, AID_SYSTEM); return fd; } /* we didn't find an available file, so we clobber the oldest one */ snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", oldest); fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); fchown(fd, AID_SYSTEM, AID_SYSTEM); return fd; }
ASTfunction_declaration::ASTfunction_declaration (OSLCompilerImpl *comp, TypeSpec type, ustring name, ASTNode *form, ASTNode *stmts, ASTNode *meta) : ASTNode (function_declaration_node, comp, 0, meta, form, stmts), m_name(name), m_sym(NULL), m_is_builtin(false) { m_typespec = type; Symbol *f = comp->symtab().clash (name); if (f && f->symtype() != SymTypeFunction) { error ("\"%s\" already declared in this scope as a ", name.c_str(), f->typespec().string().c_str()); // FIXME -- print the file and line of the other definition f = NULL; } // FIXME -- allow multiple function declarations, but only if they // aren't the same polymorphic type. if (name[0] == '_' && name[1] == '_' && name[2] == '_') { error ("\"%s\" : sorry, can't start with three underscores", name.c_str()); } m_sym = new FunctionSymbol (name, type, this); func()->nextpoly ((FunctionSymbol *)f); std::string argcodes = oslcompiler->code_from_type (m_typespec); for (ASTNode *arg = form; arg; arg = arg->nextptr()) { const TypeSpec &t (arg->typespec()); if (t == TypeSpec() /* UNKNOWN */) { m_typespec = TypeDesc::UNKNOWN; return; } argcodes += oslcompiler->code_from_type (t); ASSERT (arg->nodetype() == variable_declaration_node); ASTvariable_declaration *v = (ASTvariable_declaration *)arg; if (v->init()) v->error ("function parameter '%s' may not have a default initializer.", v->name().c_str()); } func()->argcodes (ustring (argcodes)); oslcompiler->symtab().insert (m_sym); // Typecheck it right now, upon declaration typecheck (typespec ()); }
void walkswitch(Node *sw) { /* * reorder the body into (OLIST, cases, statements) * cases have OGOTO into statements. * both have inserted OBREAK statements */ if(sw->ntest == N) { sw->ntest = nodbool(1); typecheck(&sw->ntest, Erv); } if(sw->ntest->op == OTYPESW) { typeswitch(sw); //dump("sw", sw); return; } exprswitch(sw); }
void walkswitch(Node *sw) { /* * reorder the body into (OLIST, cases, statements) * cases have OGOTO into statements. * both have inserted OBREAK statements */ if(sw->ntest == N) { sw->ntest = nodbool(1); typecheck(&sw->ntest, Erv); } if(sw->ntest->op == OTYPESW) { typeswitch(sw); //dump("sw", sw); return; } exprswitch(sw); // Discard old AST elements after a walk. They can confuse racewealk. sw->ntest = nil; sw->list = nil; }
void typecheckrange(Node *n) { char *why; Type *t, *t1, *t2; Node *v1, *v2; NodeList *ll; // delicate little dance. see typecheckas2 for(ll=n->list; ll; ll=ll->next) if(ll->n->defn != n) typecheck(&ll->n, Erv | Easgn); typecheck(&n->right, Erv); if((t = n->right->type) == T) goto out; if(isptr[t->etype] && isfixedarray(t->type)) t = t->type; n->type = t; switch(t->etype) { default: yyerror("cannot range over %lN", n->right); goto out; case TARRAY: t1 = types[TINT]; t2 = t->type; break; case TMAP: t1 = t->down; t2 = t->type; break; case TCHAN: if(!(t->chan & Crecv)) { yyerror("invalid operation: range %N (receive from send-only type %T)", n->right, n->right->type); goto out; } t1 = t->type; t2 = nil; if(count(n->list) == 2) goto toomany; break; case TSTRING: t1 = types[TINT]; t2 = runetype; break; } if(count(n->list) > 2) { toomany: yyerror("too many variables in range"); } v1 = n->list->n; v2 = N; if(n->list->next) v2 = n->list->next->n; if(v1->defn == n) v1->type = t1; else if(v1->type != T && assignop(t1, v1->type, &why) == 0) yyerror("cannot assign type %T to %lN in range%s", t1, v1, why); if(v2) { if(v2->defn == n) v2->type = t2; else if(v2->type != T && assignop(t2, v2->type, &why) == 0) yyerror("cannot assign type %T to %lN in range%s", t2, v2, why); } out: typechecklist(n->nbody, Etop); // second half of dance n->typecheck = 1; for(ll=n->list; ll; ll=ll->next) if(ll->n->typecheck == 0) typecheck(&ll->n, Erv | Easgn); }
void anylit(int ctxt, Node *n, Node *var, NodeList **init) { Type *t; Node *a, *vstat; t = n->type; switch(n->op) { default: fatal("anylit: not lit"); case OSTRUCTLIT: if(t->etype != TSTRUCT) fatal("anylit: not struct"); if(simplename(var)) { if(ctxt == 0) { // lay out static data vstat = staticname(t, ctxt); structlit(ctxt, 1, n, vstat, init); // copy static to var a = nod(OAS, var, vstat); typecheck(&a, Etop); walkexpr(&a, init); *init = list(*init, a); // add expressions to automatic structlit(ctxt, 2, n, var, init); break; } structlit(ctxt, 1, n, var, init); structlit(ctxt, 2, n, var, init); break; } // initialize of not completely specified if(count(n->list) < structcount(t)) { a = nod(OAS, var, N); typecheck(&a, Etop); walkexpr(&a, init); *init = list(*init, a); } structlit(ctxt, 3, n, var, init); break; case OARRAYLIT: if(t->etype != TARRAY) fatal("anylit: not array"); if(t->bound < 0) { slicelit(ctxt, n, var, init); break; } if(simplename(var)) { if(ctxt == 0) { // lay out static data vstat = staticname(t, ctxt); arraylit(1, 1, n, vstat, init); // copy static to automatic a = nod(OAS, var, vstat); typecheck(&a, Etop); walkexpr(&a, init); *init = list(*init, a); // add expressions to automatic arraylit(ctxt, 2, n, var, init); break; } arraylit(ctxt, 1, n, var, init); arraylit(ctxt, 2, n, var, init); break; } // initialize of not completely specified if(count(n->list) < t->bound) { a = nod(OAS, var, N); typecheck(&a, Etop); walkexpr(&a, init); *init = list(*init, a); } arraylit(ctxt, 3, n, var, init); break; case OMAPLIT: if(t->etype != TMAP) fatal("anylit: not map"); maplit(ctxt, n, var, init); break; } }
static void maplit(int ctxt, Node *n, Node *var, NodeList **init) { Node *r, *a; NodeList *l; int nerr, b; Type *t, *tk, *tv, *t1; Node *vstat, *index, *value; Sym *syma, *symb; ctxt = 0; // make the map var nerr = nerrors; a = nod(OMAKE, N, N); a->list = list1(typenod(n->type)); litas(var, a, init); // count the initializers b = 0; for(l=n->list; l; l=l->next) { r = l->n; if(r->op != OKEY) fatal("slicelit: rhs not OKEY: %N", r); index = r->left; value = r->right; if(isliteral(index) && isliteral(value)) b++; } t = T; if(b != 0) { // build type [count]struct { a Tindex, b Tvalue } t = n->type; tk = t->down; tv = t->type; symb = lookup("b"); t = typ(TFIELD); t->type = tv; t->sym = symb; syma = lookup("a"); t1 = t; t = typ(TFIELD); t->type = tk; t->sym = syma; t->down = t1; t1 = t; t = typ(TSTRUCT); t->type = t1; t1 = t; t = typ(TARRAY); t->bound = b; t->type = t1; dowidth(t); // make and initialize static array vstat = staticname(t, ctxt); b = 0; for(l=n->list; l; l=l->next) { r = l->n; if(r->op != OKEY) fatal("slicelit: rhs not OKEY: %N", r); index = r->left; value = r->right; if(isliteral(index) && isliteral(value)) { // build vstat[b].a = key; a = nodintconst(b); a = nod(OINDEX, vstat, a); a = nod(ODOT, a, newname(syma)); a = nod(OAS, a, index); typecheck(&a, Etop); walkexpr(&a, init); a->dodata = 2; *init = list(*init, a); // build vstat[b].b = value; a = nodintconst(b); a = nod(OINDEX, vstat, a); a = nod(ODOT, a, newname(symb)); a = nod(OAS, a, value); typecheck(&a, Etop); walkexpr(&a, init); a->dodata = 2; *init = list(*init, a); b++; } } // loop adding structure elements to map // for i = 0; i < len(vstat); i++ { // map[vstat[i].a] = vstat[i].b // } index = nod(OXXX, N, N); tempname(index, types[TINT]); a = nod(OINDEX, vstat, index); a->etype = 1; // no bounds checking a = nod(ODOT, a, newname(symb)); r = nod(OINDEX, vstat, index); r->etype = 1; // no bounds checking r = nod(ODOT, r, newname(syma)); r = nod(OINDEX, var, r); r = nod(OAS, r, a); a = nod(OFOR, N, N); a->nbody = list1(r); a->ninit = list1(nod(OAS, index, nodintconst(0))); a->ntest = nod(OLT, index, nodintconst(t->bound)); a->nincr = nod(OASOP, index, nodintconst(1)); a->nincr->etype = OADD; typecheck(&a, Etop); walkstmt(&a); *init = list(*init, a); } // put in dynamic entries one-at-a-time for(l=n->list; l; l=l->next) { r = l->n; if(r->op != OKEY) fatal("slicelit: rhs not OKEY: %N", r); index = r->left; value = r->right; if(isliteral(index) && isliteral(value)) continue; // build list of var[c] = expr a = nod(OINDEX, var, r->left); a = nod(OAS, a, r->right); typecheck(&a, Etop); walkexpr(&a, init); if(nerr != nerrors) break; *init = list(*init, a); } }
sexp* add_defn(sexp* e, sexp* defn) { typecheck(defn, DEFN_SEXP, "Adding non-definition to environment"); return pair_sexp(defn, e); }
sexp* builtin_div(sexp* args) { TWO_ARGS("/"); typecheck(obj1, NUMBER_SEXP, "Dividing a non-number"); typecheck(obj2, NUMBER_SEXP, "Dividing a non-number"); return number_sexp(obj1->number / obj2->number); }
/* * convert switch of the form * switch v := i.(type) { case t1: ..; case t2: ..; } * into if statements */ void typeswitch(Node *sw) { Node *def; NodeList *cas; Node *a; Case *c, *c0, *c1; int ncase; Type *t; if(sw->ntest == nil) return; if(sw->ntest->right == nil) { setlineno(sw); yyerror("type switch must have an assignment"); return; } walkexpr(&sw->ntest->right, &sw->ninit); if(!istype(sw->ntest->right->type, TINTER)) { yyerror("type switch must be on an interface"); return; } cas = nil; /* * predeclare temporary variables * and the boolean var */ facename = nod(OXXX, N, N); tempname(facename, sw->ntest->right->type); a = nod(OAS, facename, sw->ntest->right); typecheck(&a, Etop); cas = list(cas, a); casebody(sw, facename); boolname = nod(OXXX, N, N); tempname(boolname, types[TBOOL]); typecheck(&boolname, Erv); hashname = nod(OXXX, N, N); tempname(hashname, types[TUINT32]); typecheck(&hashname, Erv); t = sw->ntest->right->type; if(isnilinter(t)) a = syslook("efacethash", 1); else a = syslook("ifacethash", 1); argtype(a, t); a = nod(OCALL, a, N); a->list = list1(facename); a = nod(OAS, hashname, a); typecheck(&a, Etop); cas = list(cas, a); c0 = mkcaselist(sw, Stype); if(c0 != C && c0->type == Tdefault) { def = c0->node->right; c0 = c0->link; } else { def = nod(OBREAK, N, N); } loop: if(c0 == C) { cas = list(cas, def); sw->nbody = concat(cas, sw->nbody); sw->list = nil; walkstmtlist(sw->nbody); return; } // deal with the variables one-at-a-time if(c0->type != Ttypeconst) { a = typebsw(c0, 1); cas = list(cas, a); c0 = c0->link; goto loop; } // do binary search on run of constants ncase = 1; for(c=c0; c->link!=C; c=c->link) { if(c->link->type != Ttypeconst) break; ncase++; } // break the chain at the count c1 = c->link; c->link = C; // sort and compile constants c0 = csort(c0, typecmp); a = typebsw(c0, ncase); cas = list(cas, a); c0 = c1; goto loop; }
void typecheckrange(Node *n) { int op, et; Type *t, *t1, *t2; Node *v1, *v2; NodeList *ll; // delicate little dance. see typecheckas2 for(ll=n->list; ll; ll=ll->next) if(ll->n->defn != n) typecheck(&ll->n, Erv | Easgn); typecheck(&n->right, Erv); if((t = n->right->type) == T) goto out; n->type = t; switch(t->etype) { default: yyerror("cannot range over %+N", n->right); goto out; case TARRAY: t1 = types[TINT]; t2 = t->type; break; case TMAP: t1 = t->down; t2 = t->type; break; case TCHAN: t1 = t->type; t2 = nil; if(count(n->list) == 2) goto toomany; break; case TSTRING: t1 = types[TINT]; t2 = types[TINT]; break; } if(count(n->list) > 2) { toomany: yyerror("too many variables in range"); } v1 = n->list->n; v2 = N; if(n->list->next) v2 = n->list->next->n; if(v1->defn == n) v1->type = t1; else if(v1->type != T && checkconv(t1, v1->type, 0, &op, &et) < 0) yyerror("cannot assign type %T to %+N", t1, v1); if(v2) { if(v2->defn == n) v2->type = t2; else if(v2->type != T && checkconv(t2, v2->type, 0, &op, &et) < 0) yyerror("cannot assign type %T to %+N", t1, v1); } out: typechecklist(n->nbody, Etop); // second half of dance n->typecheck = 1; for(ll=n->list; ll; ll=ll->next) if(ll->n->typecheck == 0) typecheck(&ll->n, Erv | Easgn); }
/* Typing driver */ void infer_typing () { init_typing (); meta_typecheck (); typecheck (); };
// walkexpr and walkstmt combined // walks the tree and adds calls to the // instrumentation code to top-level (statement) nodes' init static void racewalknode(Node **np, NodeList **init, int wr, int skip) { Node *n, *n1; NodeList *l; NodeList *fini; n = *np; if(n == N) return; if(debug['w'] > 1) dump("racewalk-before", n); setlineno(n); if(init == nil) fatal("racewalk: bad init list"); if(init == &n->ninit) { // If init == &n->ninit and n->ninit is non-nil, // racewalknode might append it to itself. // nil it out and handle it separately before putting it back. l = n->ninit; n->ninit = nil; racewalklist(l, nil); racewalknode(&n, &l, wr, skip); // recurse with nil n->ninit appendinit(&n, l); *np = n; return; } racewalklist(n->ninit, nil); switch(n->op) { default: fatal("racewalk: unknown node type %O", n->op); case OASOP: case OAS: case OAS2: case OAS2RECV: case OAS2FUNC: case OAS2MAPR: racewalknode(&n->left, init, 1, 0); racewalknode(&n->right, init, 0, 0); goto ret; case OCFUNC: case OVARKILL: // can't matter goto ret; case OBLOCK: if(n->list == nil) goto ret; switch(n->list->n->op) { case OCALLFUNC: case OCALLMETH: case OCALLINTER: // Blocks are used for multiple return function calls. // x, y := f() becomes BLOCK{CALL f, AS x [SP+0], AS y [SP+n]} // We don't want to instrument between the statements because it will // smash the results. racewalknode(&n->list->n, &n->list->n->ninit, 0, 0); fini = nil; racewalklist(n->list->next, &fini); n->list = concat(n->list, fini); break; default: // Ordinary block, for loop initialization or inlined bodies. racewalklist(n->list, nil); break; } goto ret; case ODEFER: racewalknode(&n->left, init, 0, 0); goto ret; case OPROC: racewalknode(&n->left, init, 0, 0); goto ret; case OCALLINTER: racewalknode(&n->left, init, 0, 0); goto ret; case OCALLFUNC: // Instrument dst argument of runtime.writebarrier* calls // as we do not instrument runtime code. if(n->left->sym != S && n->left->sym->pkg == runtimepkg && strncmp(n->left->sym->name, "writebarrier", 12) == 0) { // Find the dst argument. // The list can be reordered, so it's not necessary just the first or the second element. for(l = n->list; l; l = l->next) { if(strcmp(n->left->sym->name, "writebarrierfat") == 0) { if(l->n->left->xoffset == widthptr) break; } else { if(l->n->left->xoffset == 0) break; } } if(l == nil) fatal("racewalk: writebarrier no arg"); if(l->n->right->op != OADDR) fatal("racewalk: writebarrier bad arg"); callinstr(&l->n->right->left, init, 1, 0); } racewalknode(&n->left, init, 0, 0); goto ret; case ONOT: case OMINUS: case OPLUS: case OREAL: case OIMAG: case OCOM: racewalknode(&n->left, init, wr, 0); goto ret; case ODOTINTER: racewalknode(&n->left, init, 0, 0); goto ret; case ODOT: racewalknode(&n->left, init, 0, 1); callinstr(&n, init, wr, skip); goto ret; case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND racewalknode(&n->left, init, 0, 0); callinstr(&n, init, wr, skip); goto ret; case OIND: // *p racewalknode(&n->left, init, 0, 0); callinstr(&n, init, wr, skip); goto ret; case OSPTR: case OLEN: case OCAP: racewalknode(&n->left, init, 0, 0); if(istype(n->left->type, TMAP)) { n1 = nod(OCONVNOP, n->left, N); n1->type = ptrto(types[TUINT8]); n1 = nod(OIND, n1, N); typecheck(&n1, Erv); callinstr(&n1, init, 0, skip); } goto ret; case OLSH: case ORSH: case OLROT: case OAND: case OANDNOT: case OOR: case OXOR: case OSUB: case OMUL: case OHMUL: case OEQ: case ONE: case OLT: case OLE: case OGE: case OGT: case OADD: case OCOMPLEX: racewalknode(&n->left, init, wr, 0); racewalknode(&n->right, init, wr, 0); goto ret; case OANDAND: case OOROR: racewalknode(&n->left, init, wr, 0); // walk has ensured the node has moved to a location where // side effects are safe. // n->right may not be executed, // so instrumentation goes to n->right->ninit, not init. racewalknode(&n->right, &n->right->ninit, wr, 0); goto ret; case ONAME: callinstr(&n, init, wr, skip); goto ret; case OCONV: racewalknode(&n->left, init, wr, 0); goto ret; case OCONVNOP: racewalknode(&n->left, init, wr, 0); goto ret; case ODIV: case OMOD: racewalknode(&n->left, init, wr, 0); racewalknode(&n->right, init, wr, 0); goto ret; case OINDEX: if(!isfixedarray(n->left->type)) racewalknode(&n->left, init, 0, 0); else if(!islvalue(n->left)) { // index of unaddressable array, like Map[k][i]. racewalknode(&n->left, init, wr, 0); racewalknode(&n->right, init, 0, 0); goto ret; } racewalknode(&n->right, init, 0, 0); if(n->left->type->etype != TSTRING) callinstr(&n, init, wr, skip); goto ret; case OSLICE: case OSLICEARR: case OSLICE3: case OSLICE3ARR: // Seems to only lead to double instrumentation. //racewalknode(&n->left, init, 0, 0); goto ret; case OADDR: racewalknode(&n->left, init, 0, 1); goto ret; case OEFACE: racewalknode(&n->left, init, 0, 0); racewalknode(&n->right, init, 0, 0); goto ret; case OITAB: racewalknode(&n->left, init, 0, 0); goto ret; // should not appear in AST by now case OSEND: case ORECV: case OCLOSE: case ONEW: case OXCASE: case OXFALL: case OCASE: case OPANIC: case ORECOVER: case OCONVIFACE: case OCMPIFACE: case OMAKECHAN: case OMAKEMAP: case OMAKESLICE: case OCALL: case OCOPY: case OAPPEND: case ORUNESTR: case OARRAYBYTESTR: case OARRAYRUNESTR: case OSTRARRAYBYTE: case OSTRARRAYRUNE: case OINDEXMAP: // lowered to call case OCMPSTR: case OADDSTR: case ODOTTYPE: case ODOTTYPE2: case OAS2DOTTYPE: case OCALLPART: // lowered to PTRLIT case OCLOSURE: // lowered to PTRLIT case ORANGE: // lowered to ordinary for loop case OARRAYLIT: // lowered to assignments case OMAPLIT: case OSTRUCTLIT: yyerror("racewalk: %O must be lowered by now", n->op); goto ret; // impossible nodes: only appear in backend. case ORROTC: case OEXTEND: yyerror("racewalk: %O cannot exist now", n->op); goto ret; // just do generic traversal case OFOR: case OIF: case OCALLMETH: case ORETURN: case ORETJMP: case OSWITCH: case OSELECT: case OEMPTY: case OBREAK: case OCONTINUE: case OFALL: case OGOTO: case OLABEL: goto ret; // does not require instrumentation case OPRINT: // don't bother instrumenting it case OPRINTN: // don't bother instrumenting it case OCHECKNIL: // always followed by a read. case OPARAM: // it appears only in fn->exit to copy heap params back case OCLOSUREVAR:// immutable pointer to captured variable case ODOTMETH: // either part of CALLMETH or CALLPART (lowered to PTRLIT) case OINDREG: // at this stage, only n(SP) nodes from nodarg case ODCL: // declarations (without value) cannot be races case ODCLCONST: case ODCLTYPE: case OTYPE: case ONONAME: case OLITERAL: case OSLICESTR: // always preceded by bounds checking, avoid double instrumentation. case OTYPESW: // ignored by code generation, do not instrument. goto ret; } ret: if(n->op != OBLOCK) // OBLOCK is handled above in a special way. racewalklist(n->list, init); if(n->ntest != N) racewalknode(&n->ntest, &n->ntest->ninit, 0, 0); if(n->nincr != N) racewalknode(&n->nincr, &n->nincr->ninit, 0, 0); racewalklist(n->nbody, nil); racewalklist(n->nelse, nil); racewalklist(n->rlist, nil); *np = n; }
bool cbmc_parseoptionst::get_goto_program( const optionst &options, bmct &bmc, goto_functionst &goto_functions) { if(cmdline.args.size()==0) { error("Please provide a program to verify"); return true; } try { if(cmdline.args.size()==1 && is_goto_binary(cmdline.args[0])) { status("Reading GOTO program from file"); if(read_goto_binary(cmdline.args[0], context, goto_functions, get_message_handler())) return true; config.ansi_c.set_from_context(context); if(cmdline.isset("show-symbol-table")) { show_symbol_table(); return true; } if(context.symbols.find(ID_main)==context.symbols.end()) { error("The goto binary has no entry point; please complete linking"); return true; } } else { if(parse()) return true; if(typecheck()) return true; if(get_modules(bmc)) return true; if(final()) return true; // we no longer need any parse trees or language files clear_parse(); if(cmdline.isset("show-symbol-table")) { show_symbol_table(); return true; } if(context.symbols.find(ID_main)==context.symbols.end()) { error("No entry point; please provide a main function"); return true; } status("Generating GOTO Program"); goto_convert( context, options, goto_functions, ui_message_handler); } // finally add the library status("Adding CPROVER library"); link_to_library( context, goto_functions, options, ui_message_handler); if(process_goto_program(options, goto_functions)) return true; } catch(const char *e) { error(e); return true; } catch(const std::string e) { error(e); return true; } catch(int) { return true; } catch(std::bad_alloc) { error("Out of memory"); return true; } return false; }
/* * look for * unsafe.Sizeof * unsafe.Offsetof * rewrite with a constant */ Node* unsafenmagic(Node *fn, NodeList *args) { Node *r, *n; Sym *s; Type *t, *tr; long v; Val val; if(fn == N || fn->op != ONAME || (s = fn->sym) == S) goto no; if(strcmp(s->package, "unsafe") != 0) goto no; if(args == nil) { yyerror("missing argument for %S", s); goto no; } r = args->n; n = nod(OLITERAL, N, N); if(strcmp(s->name, "Sizeof") == 0) { typecheck(&r, Erv); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; if(tr == T) goto no; v = tr->width; goto yes; } if(strcmp(s->name, "Offsetof") == 0) { if(r->op != ODOT && r->op != ODOTPTR) goto no; typecheck(&r, Erv); v = r->xoffset; goto yes; } if(strcmp(s->name, "Alignof") == 0) { typecheck(&r, Erv); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; if(tr == T) goto no; // make struct { byte; T; } t = typ(TSTRUCT); t->type = typ(TFIELD); t->type->type = types[TUINT8]; t->type->down = typ(TFIELD); t->type->down->type = tr; // compute struct widths dowidth(t); // the offset of T is its required alignment v = t->type->down->width; goto yes; } no: return N; yes: if(args->next != nil) yyerror("extra arguments for %S", s); // any side effects disappear; ignore init val.ctype = CTINT; val.u.xval = mal(sizeof(*n->val.u.xval)); mpmovecfix(val.u.xval, v); n = nod(OLITERAL, N, N); n->val = val; n->type = types[TINT]; return n; }
void fninit(NodeList *n) { int i; Node *gatevar; Node *a, *b, *fn; NodeList *r; uint32 h; Sym *s, *initsym; if(debug['A']) { // sys.go or unsafe.go during compiler build return; } n = initfix(n); if(!anyinit(n)) return; r = nil; // (1) snprint(namebuf, sizeof(namebuf), "initdone·"); gatevar = newname(lookup(namebuf)); addvar(gatevar, types[TUINT8], PEXTERN); // (2) maxarg = 0; snprint(namebuf, sizeof(namebuf), "init"); fn = nod(ODCLFUNC, N, N); initsym = lookup(namebuf); fn->nname = newname(initsym); fn->nname->defn = fn; fn->nname->ntype = nod(OTFUNC, N, N); declare(fn->nname, PFUNC); funchdr(fn); // (3) a = nod(OIF, N, N); a->ntest = nod(ONE, gatevar, nodintconst(0)); r = list(r, a); // (4) b = nod(OIF, N, N); b->ntest = nod(OEQ, gatevar, nodintconst(2)); b->nbody = list1(nod(ORETURN, N, N)); a->nbody = list1(b); // (5) b = syslook("throwinit", 0); b = nod(OCALL, b, N); a->nbody = list(a->nbody, b); // (6) a = nod(OAS, gatevar, nodintconst(1)); r = list(r, a); // (7) for(h=0; h<NHASH; h++) for(s = hash[h]; s != S; s = s->link) { if(s->name[0] != 'i' || strcmp(s->name, "init") != 0) continue; if(s->def == N) continue; if(s == initsym) continue; // could check that it is fn of no args/returns a = nod(OCALL, s->def, N); r = list(r, a); } // (8) r = concat(r, n); // (9) // could check that it is fn of no args/returns for(i=1;; i++) { snprint(namebuf, sizeof(namebuf), "init·%d", i); s = lookup(namebuf); if(s->def == N) break; a = nod(OCALL, s->def, N); r = list(r, a); } // (10) a = nod(OAS, gatevar, nodintconst(2)); r = list(r, a); // (11) a = nod(ORETURN, N, N); r = list(r, a); exportsym(fn->nname); fn->nbody = r; funcbody(fn); curfn = fn; typecheck(&fn, Etop); typechecklist(r, Etop); curfn = nil; funccompile(fn, 0); }
void walkrange(Node *n) { Node *ohv1, *hv1, *hv2; // hidden (old) val 1, 2 Node *ha, *hit; // hidden aggregate, iterator Node *hn, *hp; // hidden len, pointer Node *hb; // hidden bool Node *a, *v1, *v2; // not hidden aggregate, val 1, 2 Node *fn, *tmp; NodeList *body, *init; Type *th, *t; int lno; t = n->type; init = nil; a = n->right; lno = setlineno(a); if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) { a = nod(OCONV, n->right, N); a->type = types[TSTRING]; } v1 = n->list->n; v2 = N; if(n->list->next) v2 = n->list->next->n; hv2 = N; if(v2 == N && t->etype == TARRAY) { // will have just one reference to argument. // no need to make a potentially expensive copy. ha = a; } else { ha = temp(a->type); init = list(init, nod(OAS, ha, a)); } switch(t->etype) { default: fatal("walkrange"); case TARRAY: hv1 = temp(types[TINT]); hn = temp(types[TINT]); hp = nil; init = list(init, nod(OAS, hv1, N)); init = list(init, nod(OAS, hn, nod(OLEN, ha, N))); if(v2) { hp = temp(ptrto(n->type->type)); tmp = nod(OINDEX, ha, nodintconst(0)); tmp->etype = 1; // no bounds check init = list(init, nod(OAS, hp, nod(OADDR, tmp, N))); } n->ntest = nod(OLT, hv1, hn); n->nincr = nod(OASOP, hv1, nodintconst(1)); n->nincr->etype = OADD; if(v2 == N) body = list1(nod(OAS, v1, hv1)); else { a = nod(OAS2, N, N); a->list = list(list1(v1), v2); a->rlist = list(list1(hv1), nod(OIND, hp, N)); body = list1(a); tmp = nod(OADD, hp, nodintconst(t->type->width)); tmp->type = hp->type; tmp->typecheck = 1; tmp->right->type = types[tptr]; tmp->right->typecheck = 1; body = list(body, nod(OAS, hp, tmp)); } break; case TMAP: th = typ(TARRAY); th->type = ptrto(types[TUINT8]); // see ../../pkg/runtime/hashmap.h:/hash_iter // Size in words. th->bound = 5 + 4*3 + 4*4/widthptr; hit = temp(th); fn = syslook("mapiterinit", 1); argtype(fn, t->down); argtype(fn, t->type); argtype(fn, th); init = list(init, mkcall1(fn, T, nil, typename(t), ha, nod(OADDR, hit, N))); n->ntest = nod(ONE, nod(OINDEX, hit, nodintconst(0)), nodnil()); fn = syslook("mapiternext", 1); argtype(fn, th); n->nincr = mkcall1(fn, T, nil, nod(OADDR, hit, N)); if(v2 == N) { fn = syslook("mapiter1", 1); argtype(fn, th); argtype(fn, t->down); a = nod(OAS, v1, mkcall1(fn, t->down, nil, nod(OADDR, hit, N))); } else { fn = syslook("mapiter2", 1); argtype(fn, th); argtype(fn, t->down); argtype(fn, t->type); a = nod(OAS2, N, N); a->list = list(list1(v1), v2); a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, nod(OADDR, hit, N))); } body = list1(a); break; case TCHAN: hv1 = temp(t->type); hb = temp(types[TBOOL]); n->ntest = nod(ONE, hb, nodbool(0)); a = nod(OAS2RECV, N, N); a->typecheck = 1; a->list = list(list1(hv1), hb); a->rlist = list1(nod(ORECV, ha, N)); n->ntest->ninit = list1(a); body = list1(nod(OAS, v1, hv1)); break; case TSTRING: ohv1 = temp(types[TINT]); hv1 = temp(types[TINT]); init = list(init, nod(OAS, hv1, N)); if(v2 == N) a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1)); else { hv2 = temp(runetype); a = nod(OAS2, N, N); a->list = list(list1(hv1), hv2); fn = syslook("stringiter2", 0); a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, ha, hv1)); } n->ntest = nod(ONE, hv1, nodintconst(0)); n->ntest->ninit = list(list1(nod(OAS, ohv1, hv1)), a); body = list1(nod(OAS, v1, ohv1)); if(v2 != N) body = list(body, nod(OAS, v2, hv2)); break; } n->op = OFOR; typechecklist(init, Etop); n->ninit = concat(n->ninit, init); typechecklist(n->ntest->ninit, Etop); typecheck(&n->ntest, Erv); typecheck(&n->nincr, Etop); typechecklist(body, Etop); n->nbody = concat(body, n->nbody); walkstmt(&n); lineno = lno; }
void walkrange(Node *n) { Node *ohv1, *hv1, *hv2; // hidden (old) val 1, 2 Node *ha, *hit; // hidden aggregate, iterator Node *a, *v1, *v2; // not hidden aggregate, val 1, 2 Node *fn; NodeList *body, *init; Type *th, *t; t = n->type; init = nil; a = n->right; if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) { a = nod(OCONV, n->right, N); a->type = types[TSTRING]; } ha = nod(OXXX, N, N); tempname(ha, a->type); init = list(init, nod(OAS, ha, a)); v1 = n->list->n; hv1 = N; v2 = N; if(n->list->next) v2 = n->list->next->n; hv2 = N; switch(t->etype) { default: fatal("walkrange"); case TARRAY: hv1 = nod(OXXX, N, n); tempname(hv1, types[TINT]); init = list(init, nod(OAS, hv1, N)); n->ntest = nod(OLT, hv1, nod(OLEN, ha, N)); n->nincr = nod(OASOP, hv1, nodintconst(1)); n->nincr->etype = OADD; body = list1(nod(OAS, v1, hv1)); if(v2) body = list(body, nod(OAS, v2, nod(OINDEX, ha, hv1))); break; case TMAP: th = typ(TARRAY); th->type = ptrto(types[TUINT8]); th->bound = (sizeof(struct Hiter) + widthptr - 1) / widthptr; hit = nod(OXXX, N, N); tempname(hit, th); fn = syslook("mapiterinit", 1); argtype(fn, t->down); argtype(fn, t->type); argtype(fn, th); init = list(init, mkcall1(fn, T, nil, ha, nod(OADDR, hit, N))); n->ntest = nod(ONE, nod(OINDEX, hit, nodintconst(0)), nodnil()); fn = syslook("mapiternext", 1); argtype(fn, th); n->nincr = mkcall1(fn, T, nil, nod(OADDR, hit, N)); if(v2 == N) { fn = syslook("mapiter1", 1); argtype(fn, th); argtype(fn, t->down); a = nod(OAS, v1, mkcall1(fn, t->down, nil, nod(OADDR, hit, N))); } else { fn = syslook("mapiter2", 1); argtype(fn, th); argtype(fn, t->down); argtype(fn, t->type); a = nod(OAS2, N, N); a->list = list(list1(v1), v2); a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, nod(OADDR, hit, N))); } body = list1(a); break; case TCHAN: hv1 = nod(OXXX, N, n); tempname(hv1, t->type); n->ntest = nod(ONOT, nod(OCLOSED, ha, N), N); n->ntest->ninit = list1(nod(OAS, hv1, nod(ORECV, ha, N))); body = list1(nod(OAS, v1, hv1)); break; case TSTRING: ohv1 = nod(OXXX, N, N); tempname(ohv1, types[TINT]); hv1 = nod(OXXX, N, N); tempname(hv1, types[TINT]); init = list(init, nod(OAS, hv1, N)); if(v2 == N) a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1)); else { hv2 = nod(OXXX, N, N); tempname(hv2, types[TINT]); a = nod(OAS2, N, N); a->list = list(list1(hv1), hv2); fn = syslook("stringiter2", 0); a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, ha, hv1)); } n->ntest = nod(ONE, hv1, nodintconst(0)); n->ntest->ninit = list(list1(nod(OAS, ohv1, hv1)), a); body = list1(nod(OAS, v1, ohv1)); if(v2 != N) body = list(body, nod(OAS, v2, hv2)); break; } n->op = OFOR; typechecklist(init, Etop); n->ninit = concat(n->ninit, init); typechecklist(n->ntest->ninit, Etop); typecheck(&n->ntest, Erv); typecheck(&n->nincr, Etop); typechecklist(body, Etop); n->nbody = concat(body, n->nbody); walkstmt(&n); }
int preparet::doit() { register_languages(); try { // do we have a goto binary? if(cmdline.args.size()==1 && is_goto_binary(cmdline.args[0])) { status("Reading GOTO program from file"); if(read_goto_binary(cmdline.args[0], context, goto_functions, get_message_handler())) return 1; config.ansi_c.set_from_context(context); } else { // // parsing // if(parse()) return 1; // // type checking // if(typecheck()) return 1; // // final adjustments // if(final()) return 1; } { int return_value_get_sync_modules=get_sync_modules(); if(return_value_get_sync_modules>=0) return return_value_get_sync_modules; } { int return_value_get_async_modules=get_async_modules(); if(return_value_get_async_modules>=0) return return_value_get_async_modules; } if(cmdline.isset("show-claims")) { show_claims(ns, get_ui(), goto_functions); return 0; } // get the user provided predicates if(cmdline.isset("predicates")) get_predicates( cmdline.getval("predicates"), get_message_handler(), ns, user_provided_predicates); } catch(const char *e) { error(e); return 1; } catch(const std::string e) { error(e); return 1; } catch(int) { return 1; } return -1; // proceed! }
/* * type check switch statement */ void typecheckswitch(Node *n) { int top, lno; Type *t; NodeList *l, *ll; Node *ncase, *nvar; Node *def; lno = lineno; typechecklist(n->ninit, Etop); if(n->ntest != N && n->ntest->op == OTYPESW) { // type switch top = Etype; typecheck(&n->ntest->right, Erv); t = n->ntest->right->type; if(t != T && t->etype != TINTER) yyerror("cannot type switch on non-interface value %+N", n->ntest->right); } else { // value switch top = Erv; if(n->ntest) { typecheck(&n->ntest, Erv); defaultlit(&n->ntest, T); t = n->ntest->type; } else t = types[TBOOL]; } n->type = t; def = N; for(l=n->list; l; l=l->next) { ncase = l->n; setlineno(n); if(ncase->list == nil) { // default if(def != N) yyerror("multiple defaults in switch (first at %L)", def->lineno); else def = ncase; } else { for(ll=ncase->list; ll; ll=ll->next) { setlineno(ll->n); typecheck(&ll->n, Erv | Etype); if(ll->n->type == T || t == T) continue; switch(top) { case Erv: // expression switch defaultlit(&ll->n, t); if(ll->n->op == OTYPE) yyerror("type %T is not an expression", ll->n->type); else if(ll->n->type != T && !eqtype(ll->n->type, t)) yyerror("case %+N in %T switch", ll->n, t); break; case Etype: // type switch if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) ; else if(ll->n->op != OTYPE && ll->n->type != T) yyerror("%#N is not a type", ll->n); break; } } } if(top == Etype && n->type != T) { ll = ncase->list; nvar = ncase->nname; if(nvar != N) { if(ll && ll->next == nil && ll->n->type != T && !istype(ll->n->type, TNIL)) { // single entry type switch nvar->ntype = typenod(ll->n->type); } else { // multiple entry type switch or default nvar->ntype = typenod(n->type); } } } typechecklist(ncase->nbody, Etop); } lineno = lno; }
sexp* builtin_sub(sexp* args) { TWO_ARGS("-"); typecheck(obj1, NUMBER_SEXP, "Subtracting a non-number"); typecheck(obj2, NUMBER_SEXP, "Subtracting a non-number"); return number_sexp(obj1->number - obj2->number); }
/* * convert switch of the form * switch v := i.(type) { case t1: ..; case t2: ..; } * into if statements */ static void typeswitch(Node *sw) { Node *def; NodeList *cas, *hash; Node *a, *n; Case *c, *c0, *c1; int ncase; Type *t; Val v; if(sw->ntest == nil) return; if(sw->ntest->right == nil) { setlineno(sw); yyerror("type switch must have an assignment"); return; } walkexpr(&sw->ntest->right, &sw->ninit); if(!istype(sw->ntest->right->type, TINTER)) { yyerror("type switch must be on an interface"); return; } cas = nil; /* * predeclare temporary variables * and the boolean var */ facename = temp(sw->ntest->right->type); a = nod(OAS, facename, sw->ntest->right); typecheck(&a, Etop); cas = list(cas, a); casebody(sw, facename); boolname = temp(types[TBOOL]); typecheck(&boolname, Erv); hashname = temp(types[TUINT32]); typecheck(&hashname, Erv); t = sw->ntest->right->type; if(isnilinter(t)) a = syslook("efacethash", 1); else a = syslook("ifacethash", 1); argtype(a, t); a = nod(OCALL, a, N); a->list = list1(facename); a = nod(OAS, hashname, a); typecheck(&a, Etop); cas = list(cas, a); c0 = mkcaselist(sw, Stype); if(c0 != C && c0->type == Tdefault) { def = c0->node->right; c0 = c0->link; } else { def = nod(OBREAK, N, N); } /* * insert if statement into each case block */ for(c=c0; c!=C; c=c->link) { n = c->node; switch(c->type) { case Ttypenil: v.ctype = CTNIL; a = nod(OIF, N, N); a->ntest = nod(OEQ, facename, nodlit(v)); typecheck(&a->ntest, Erv); a->nbody = list1(n->right); // if i==nil { goto l } n->right = a; break; case Ttypevar: case Ttypeconst: n->right = typeone(n); break; } } /* * generate list of if statements, binary search for constant sequences */ while(c0 != C) { if(c0->type != Ttypeconst) { n = c0->node; cas = list(cas, n->right); c0=c0->link; continue; } // identify run of constants c1 = c = c0; while(c->link!=C && c->link->type==Ttypeconst) c = c->link; c0 = c->link; c->link = nil; // sort by hash c1 = csort(c1, typecmp); // for debugging: linear search if(0) { for(c=c1; c!=C; c=c->link) { n = c->node; cas = list(cas, n->right); } continue; } // combine adjacent cases with the same hash ncase = 0; for(c=c1; c!=C; c=c->link) { ncase++; hash = list1(c->node->right); while(c->link != C && c->link->hash == c->hash) { hash = list(hash, c->link->node->right); c->link = c->link->link; } c->node->right = liststmt(hash); } // binary search among cases to narrow by hash cas = list(cas, typebsw(c1, ncase)); } if(nerrors == 0) { cas = list(cas, def); sw->nbody = concat(cas, sw->nbody); sw->list = nil; walkstmtlist(sw->nbody); } }
static void slicelit(int ctxt, Node *n, Node *var, NodeList **init) { Node *r, *a; NodeList *l; Type *t; Node *vstat, *vauto; Node *index, *value; int mode; // make an array type t = shallow(n->type); t->bound = mpgetfix(n->right->val.u.xval); t->width = 0; t->sym = nil; dowidth(t); if(ctxt != 0) { // put everything into static array vstat = staticname(t, ctxt); arraylit(ctxt, 1, n, vstat, init); arraylit(ctxt, 2, n, vstat, init); // copy static to slice a = nod(OSLICE, vstat, nod(OKEY, N, N)); a = nod(OAS, var, a); typecheck(&a, Etop); a->dodata = 2; *init = list(*init, a); return; } // recipe for var = []t{...} // 1. make a static array // var vstat [...]t // 2. assign (data statements) the constant part // vstat = constpart{} // 3. make an auto pointer to array and allocate heap to it // var vauto *[...]t = new([...]t) // 4. copy the static array to the auto array // *vauto = vstat // 5. assign slice of allocated heap to var // var = [0:]*auto // 6. for each dynamic part assign to the slice // var[i] = dynamic part // // an optimization is done if there is no constant part // 3. var vauto *[...]t = new([...]t) // 5. var = [0:]*auto // 6. var[i] = dynamic part // if the literal contains constants, // make static initialized array (1),(2) vstat = N; mode = getdyn(n, 1); if(mode & MODECONST) { vstat = staticname(t, ctxt); arraylit(ctxt, 1, n, vstat, init); } // make new auto *array (3 declare) vauto = nod(OXXX, N, N); tempname(vauto, ptrto(t)); // set auto to point at new heap (3 assign) a = nod(ONEW, N, N); a->list = list1(typenod(t)); a = nod(OAS, vauto, a); typecheck(&a, Etop); walkexpr(&a, init); *init = list(*init, a); if(vstat != N) { // copy static to heap (4) a = nod(OIND, vauto, N); a = nod(OAS, a, vstat); typecheck(&a, Etop); walkexpr(&a, init); *init = list(*init, a); } // make slice out of heap (5) a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N))); typecheck(&a, Etop); walkexpr(&a, init); *init = list(*init, a); // put dynamics into slice (6) for(l=n->list; l; l=l->next) { r = l->n; if(r->op != OKEY) fatal("slicelit: rhs not OKEY: %N", r); index = r->left; value = r->right; a = nod(OINDEX, var, index); a->etype = 1; // no bounds checking // TODO need to check bounds? switch(value->op) { case OARRAYLIT: if(value->type->bound < 0) break; arraylit(ctxt, 2, value, a, init); continue; case OSTRUCTLIT: structlit(ctxt, 2, value, a, init); continue; } if(isliteral(index) && isliteral(value)) continue; // build list of var[c] = expr a = nod(OAS, a, value); typecheck(&a, Etop); walkexpr(&a, init); *init = list(*init, a); } }
/* * type check switch statement */ void typecheckswitch(Node *n) { int top, lno, ptr; char *nilonly; Type *t, *badtype, *missing, *have; NodeList *l, *ll; Node *ncase, *nvar; Node *def; lno = lineno; typechecklist(n->ninit, Etop); nilonly = nil; if(n->ntest != N && n->ntest->op == OTYPESW) { // type switch top = Etype; typecheck(&n->ntest->right, Erv); t = n->ntest->right->type; if(t != T && t->etype != TINTER) yyerror("cannot type switch on non-interface value %lN", n->ntest->right); } else { // value switch top = Erv; if(n->ntest) { typecheck(&n->ntest, Erv); defaultlit(&n->ntest, T); t = n->ntest->type; } else t = types[TBOOL]; if(t) { if(!okforeq[t->etype]) yyerror("cannot switch on %lN", n->ntest); else if(t->etype == TARRAY && !isfixedarray(t)) nilonly = "slice"; else if(t->etype == TARRAY && isfixedarray(t) && algtype1(t, nil) == ANOEQ) yyerror("cannot switch on %lN", n->ntest); else if(t->etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ) yyerror("cannot switch on %lN (struct containing %T cannot be compared)", n->ntest, badtype); else if(t->etype == TFUNC) nilonly = "func"; else if(t->etype == TMAP) nilonly = "map"; } } n->type = t; def = N; for(l=n->list; l; l=l->next) { ncase = l->n; setlineno(n); if(ncase->list == nil) { // default if(def != N) yyerror("multiple defaults in switch (first at %L)", def->lineno); else def = ncase; } else { for(ll=ncase->list; ll; ll=ll->next) { setlineno(ll->n); typecheck(&ll->n, Erv | Etype); if(ll->n->type == T || t == T) continue; setlineno(ncase); switch(top) { case Erv: // expression switch defaultlit(&ll->n, t); if(ll->n->op == OTYPE) yyerror("type %T is not an expression", ll->n->type); else if(ll->n->type != T && !assignop(ll->n->type, t, nil) && !assignop(t, ll->n->type, nil)) { if(n->ntest) yyerror("invalid case %N in switch on %N (mismatched types %T and %T)", ll->n, n->ntest, ll->n->type, t); else yyerror("invalid case %N in switch (mismatched types %T and bool)", ll->n, ll->n->type); } else if(nilonly && !isconst(ll->n, CTNIL)) { yyerror("invalid case %N in switch (can only compare %s %N to nil)", ll->n, nilonly, n->ntest); } break; case Etype: // type switch if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) { ; } else if(ll->n->op != OTYPE && ll->n->type != T) { // should this be ||? yyerror("%lN is not a type", ll->n); // reset to original type ll->n = n->ntest->right; } else if(ll->n->type->etype != TINTER && t->etype == TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) { if(have && !missing->broke && !have->broke) yyerror("impossible type switch case: %lN cannot have dynamic type %T" " (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT", n->ntest->right, ll->n->type, missing->sym, have->sym, have->type, missing->sym, missing->type); else if(!missing->broke) yyerror("impossible type switch case: %lN cannot have dynamic type %T" " (missing %S method)", n->ntest->right, ll->n->type, missing->sym); } break; } } } if(top == Etype && n->type != T) { ll = ncase->list; nvar = ncase->nname; if(nvar != N) { if(ll && ll->next == nil && ll->n->type != T && !istype(ll->n->type, TNIL)) { // single entry type switch nvar->ntype = typenod(ll->n->type); } else { // multiple entry type switch or default nvar->ntype = typenod(n->type); } } } typechecklist(ncase->nbody, Etop); } lineno = lno; }
exprt ranking_synthesis_satt::instantiate(void) { find_largest_constant(body.body_relation); binary_relation_exprt toplevel_and("and"); toplevel_and.lhs() = body.body_relation; // that's R(x,x') exprt function; replace_mapt pre_replace_map; bool first=true; for(bodyt::variable_mapt::const_iterator it=body.variable_map.begin(); it!=body.variable_map.end(); it++) { if(used_variables.find(it->first)==used_variables.end()) continue; exprt var=symbol_exprt(it->first, ns.lookup(it->first).type); pre_replace_map[var] = // save the corresponding pre-var symbol_exprt(it->second, ns.lookup(it->second).type); adjust_type(var.type()); const typet type=var.type(); exprt coef=coefficient(var); unsigned width=safe_width(var, ns); assert(width!=0); exprt term("*", typet("")); term.copy_to_operands(coef, var); if(first) { function=term; first=false; } else { // cast_up(function, term); exprt t("+", typet("")); t.move_to_operands(function, term); function = t; } } if(first) // non of the interesting variables was used - bail out! { debug("Completely non-deterministic template; " "this loop does not terminate."); return false_exprt(); } // if(!largest_constant.is_zero()) // { // // add the largest constant // symbol_exprt lc_sym("termination::LC", largest_constant.type()); // exprt lc=largest_constant; // exprt lcc=coefficient(lc_sym); //// cast_up(lc, lcc); // exprt m("*", typet("")); // m.move_to_operands(lcc, lc); // //// cast_up(function, m); // exprt t("+", typet("")); // t.move_to_operands(function, m); // function = t; // } // add a constant term symbol_exprt const_sym("termination::constant", signedbv_typet(2)); exprt cc=coefficient(const_sym); // cast_up(function, cc); exprt t2("+", typet("")); t2.move_to_operands(function, cc); function=t2; contextt context; ansi_c_parse_treet pt; rankfunction_typecheckt typecheck(pt, context, ns, *message_handler); try { typecheck.typecheck_expr(function); } catch (...) { throw "TC ERROR"; } exprt pre_function = function; replace_expr(pre_replace_map, pre_function); // save the relation for later rank_relation = binary_relation_exprt(function, "<", pre_function); // base_type(rank_relation, ns); toplevel_and.rhs()=not_exprt(rank_relation); return toplevel_and; }
bool symex_parseoptionst::get_goto_program( const optionst &options, goto_functionst &goto_functions) { if(cmdline.args.empty()) { error() << "Please provide a program to verify" << eom; return true; } try { if(cmdline.args.size()==1 && is_goto_binary(cmdline.args[0])) { status() << "Reading GOTO program from file" << eom; if(read_goto_binary(cmdline.args[0], symbol_table, goto_functions, get_message_handler())) return true; config.ansi_c.set_from_symbol_table(symbol_table); if(cmdline.isset("show-symbol-table")) { show_symbol_table(); return true; } irep_idt entry_point=goto_functions.entry_point(); if(symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) { error() << "The goto binary has no entry point; please complete linking" << eom; return true; } } else if(cmdline.isset("show-parse-tree")) { if(cmdline.args.size()!=1) { error() << "Please give one source file only" << eom; return true; } std::string filename=cmdline.args[0]; #ifdef _MSC_VER std::ifstream infile(widen(filename).c_str()); #else std::ifstream infile(filename.c_str()); #endif if(!infile) { error() << "failed to open input file `" << filename << "'" << eom; return true; } languaget *language=get_language_from_filename(filename); if(language==NULL) { error() << "failed to figure out type of file `" << filename << "'" << eom; return true; } status("Parsing", filename); if(language->parse(infile, filename, get_message_handler())) { error() << "PARSING ERROR" << eom; return true; } language->show_parse(std::cout); return true; } else { if(parse()) return true; if(typecheck()) return true; if(final()) return true; // we no longer need any parse trees or language files clear_parse(); if(cmdline.isset("show-symbol-table")) { show_symbol_table(); return true; } irep_idt entry_point=goto_functions.entry_point(); if(symbol_table.symbols.find(entry_point)==symbol_table.symbols.end()) { error() << "No entry point; please provide a main function" << eom; return true; } status() << "Generating GOTO Program" << eom; goto_convert(symbol_table, goto_functions, ui_message_handler); } // finally add the library status() << "Adding CPROVER library" << eom; link_to_library(symbol_table, goto_functions, ui_message_handler); if(process_goto_program(options, goto_functions)) return true; } catch(const char *e) { error(e); return true; } catch(const std::string e) { error(e); return true; } catch(int) { return true; } catch(std::bad_alloc) { error() << "Out of memory" << eom; return true; } return false; }
/* * look for * unsafe.Sizeof * unsafe.Offsetof * rewrite with a constant */ Node* unsafenmagic(Node *nn) { Node *r, *n; Sym *s; Type *t, *tr; long v; Val val; Node *fn; NodeList *args; fn = nn->left; args = nn->list; if(safemode || fn == N || fn->op != ONAME || (s = fn->sym) == S) goto no; if(s->pkg != unsafepkg) goto no; if(args == nil) { yyerror("missing argument for %S", s); goto no; } r = args->n; if(strcmp(s->name, "Sizeof") == 0) { typecheck(&r, Erv); defaultlit(&r, T); tr = r->type; if(tr == T) goto bad; dowidth(tr); v = tr->width; goto yes; } if(strcmp(s->name, "Offsetof") == 0) { typecheck(&r, Erv); if(r->op != ODOT && r->op != ODOTPTR) goto bad; typecheck(&r, Erv); v = r->xoffset; goto yes; } if(strcmp(s->name, "Alignof") == 0) { typecheck(&r, Erv); defaultlit(&r, T); tr = r->type; if(tr == T) goto bad; // make struct { byte; T; } t = typ(TSTRUCT); t->type = typ(TFIELD); t->type->type = types[TUINT8]; t->type->down = typ(TFIELD); t->type->down->type = tr; // compute struct widths dowidth(t); // the offset of T is its required alignment v = t->type->down->width; goto yes; } no: return N; bad: yyerror("invalid expression %#N", nn); v = 0; goto ret; yes: if(args->next != nil) yyerror("extra arguments for %S", s); ret: // any side effects disappear; ignore init val.ctype = CTINT; val.u.xval = mal(sizeof(*n->val.u.xval)); mpmovecfix(val.u.xval, v); n = nod(OLITERAL, N, N); n->val = val; n->type = types[TINT]; return n; }