static int callinstr(Node **np, NodeList **init, int wr, int skip) { Node *f, *b, *n; Type *t; int class, hascalls; n = *np; //print("callinstr for %+N [ %O ] etype=%E class=%d\n", // n, n->op, n->type ? n->type->etype : -1, n->class); if(skip || n->type == T || n->type->etype >= TIDEAL) return 0; t = n->type; if(isartificial(n)) return 0; b = basenod(n); // it skips e.g. stores to ... parameter array if(isartificial(b)) return 0; class = b->class; // BUG: we _may_ want to instrument PAUTO sometimes // e.g. if we've got a local variable/method receiver // that has got a pointer inside. Whether it points to // the heap or not is impossible to know at compile time if((class&PHEAP) || class == PPARAMREF || class == PEXTERN || b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) { hascalls = 0; foreach(n, hascallspred, &hascalls); if(hascalls) { n = detachexpr(n, init); *np = n; } n = treecopy(n); makeaddable(n); if(t->etype == TSTRUCT || isfixedarray(t)) { f = mkcall(wr ? "racewriterange" : "racereadrange", T, init, uintptraddr(n), nodintconst(t->width)); } else f = mkcall(wr ? "racewrite" : "raceread", T, init, uintptraddr(n)); *init = list(*init, f); return 1; } return 0; }
void racewalk(Node *fn) { Node *nd; Node *nodpc; char s[1024]; if(ispkgin(omit_pkgs, nelem(omit_pkgs)) || isforkfunc(fn)) return; if(!ispkgin(noinst_pkgs, nelem(noinst_pkgs))) { racewalklist(fn->nbody, nil); // nothing interesting for race detector in fn->enter racewalklist(fn->exit, nil); } // nodpc is the PC of the caller as extracted by // getcallerpc. We use -widthptr(FP) for x86. // BUG: this will not work on arm. nodpc = nod(OXXX, nil, nil); *nodpc = *nodfp; nodpc->type = types[TUINTPTR]; nodpc->xoffset = -widthptr; nd = mkcall("racefuncenter", T, nil, nodpc); fn->enter = concat(list1(nd), fn->enter); nd = mkcall("racefuncexit", T, nil); fn->exit = list(fn->exit, nd); if(debug['W']) { snprint(s, sizeof(s), "after racewalk %S", fn->nname->sym); dumplist(s, fn->nbody); snprint(s, sizeof(s), "enter %S", fn->nname->sym); dumplist(s, fn->enter); snprint(s, sizeof(s), "exit %S", fn->nname->sym); dumplist(s, fn->exit); } }
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 child_random_syscalls(int childno) { int ret; unsigned int syscallnr; ret = sigsetjmp(ret_jump, 1); if (ret != 0) { if (handle_sigreturn(childno) == 0) return 0; ret = 0; } while (shm->exit_reason == STILL_RUNNING) { check_parent_pid(); while (shm->regenerating == TRUE) sleep(1); /* If the parent reseeded, we should reflect the latest seed too. */ if (shm->seed != shm->seeds[childno]) set_seed(childno); choose_syscall_table(childno); if (nr_active_syscalls == 0) { shm->exit_reason = EXIT_NO_SYSCALLS_ENABLED; goto out; } if (shm->exit_reason != STILL_RUNNING) goto out; syscallnr = rand() % nr_active_syscalls; /* If we got a syscallnr which is not actvie repeat the attempt, since another child has switched that syscall off already.*/ if (active_syscalls[syscallnr] == 0) continue; syscallnr = active_syscalls[syscallnr] - 1; if (validate_specific_syscall_silent(syscalls, syscallnr) == FALSE) { if (biarch == FALSE) { deactivate_syscall(syscallnr); } else { if (shm->do32bit[childno] == TRUE) deactivate_syscall32(syscallnr); else deactivate_syscall64(syscallnr); } continue; } shm->syscallno[childno] = syscallnr; if (syscalls_todo) { if (shm->total_syscalls_done >= syscalls_todo) { output(0, "Reached maximum syscall count (todo = %d, done = %d), exiting...\n", syscalls_todo, shm->total_syscalls_done); shm->exit_reason = EXIT_REACHED_COUNT; } } ret = mkcall(childno); } out: return ret; }