/* profInit - initialize basic block profiling options */ void prof_init(int argc, char* argv[]) { int i; static int inited; if (inited) return; inited = 1; type_init(argc, argv); if (IR) { for (i = 1; i < argc; i++) if (strncmp(argv[i], "-a", 2) == 0) { if (ncalled == -1 && process(argv[i][2] ? &argv[i][2] : "prof.out") > 0) ncalled = 0; } else if ((strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-C") == 0) && YYlink == 0) { YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); attach((Apply)bbentry, YYlink, &events.entry); attach((Apply)bbexit, YYlink, &events.returns); attach((Apply)bbfunc, YYlink, &events.exit); attach((Apply)bbvars, YYlink, &events.end); if (strcmp(argv[i], "-b") == 0) { YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); maplist = append(allocate(sizeof(struct map), PERM), maplist); ((struct map*)maplist->x)->size = 0; attach((Apply)bbcall, YYcounts, &events.calls); attach((Apply)bbincr, YYcounts, &events.points); } } } }
/* bbvars - emit definition for basic block counting data */ static void bbvars(Symbol yylink) { int i, j, n = npoints; Value v; struct map** mp; Symbol coords, files, *p; if (!YYcounts && !yylink) return; if (YYcounts) { if (n <= 0) n = 1; YYcounts->type = array(unsignedtype, n, 0); defglobal(YYcounts, BSS); } files = genident(STATIC, array(charptype, 1, 0), GLOBAL); defglobal(files, LIT); for (p = ltov(&filelist, PERM); *p; p++) defpointer((*p)->u.c.loc); defpointer(NULL); coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL); defglobal(coords, LIT); for (i = n, mp = ltov(&maplist, PERM); *mp; i -= (*mp)->size, mp++) for (j = 0; j < (*mp)->size; j++) (*IR->defconst)(U, unsignedtype->size, (v.u = (*mp)->u[j].coord, v)); if (i > 0) (*IR->space)(i * coords->type->type->size); defpointer(NULL); defglobal(yylink, DATA); defpointer(NULL); (*IR->defconst)(U, unsignedtype->size, (v.u = n, v)); defpointer(YYcounts); defpointer(coords); defpointer(files); defpointer(funclist); }
void retcode(Tree p) { Type ty; if (p == NULL) { if (events.returns) apply(events.returns, cfunc, NULL); return; } p = pointer(p); ty = assign(freturn(cfunc->type), p); if (ty == NULL) { error("illegal return type; found `%t' expected `%t'\n", p->type, freturn(cfunc->type)); return; } p = cast(p, ty); if (retv) { if (iscallb(p)) p = tree(RIGHT, p->type, tree(CALL+B, p->type, p->kids[0]->kids[0], idtree(retv)), rvalue(idtree(retv))); else { Type ty = retv->type->type; assert(isstruct(ty)); if (ty->u.sym->u.s.cfields) { ty->u.sym->u.s.cfields = 0; p = asgntree(ASGN, rvalue(idtree(retv)), p); ty->u.sym->u.s.cfields = 1; } else p = asgntree(ASGN, rvalue(idtree(retv)), p); } walk(p, 0, 0); if (events.returns) apply(events.returns, cfunc, rvalue(idtree(retv))); return; } if (events.returns) { Symbol t1 = genident(AUTO, p->type, level); addlocal(t1); walk(asgn(t1, p), 0, 0); apply(events.returns, cfunc, idtree(t1)); p = idtree(t1); } if (!isfloat(p->type)) p = cast(p, promote(p->type)); if (isptr(p->type)) { Symbol q = localaddr(p); if (q && (q->computed || q->generated)) warning("pointer to a %s is an illegal return value\n", q->scope == PARAM ? "parameter" : "local"); else if (q) warning("pointer to %s `%s' is an illegal return value\n", q->scope == PARAM ? "parameter" : "local", q->name); } walk(tree(mkop(RET,p->type), p->type, p, NULL), 0, 0); }
/* bbcall - build tree to set _callsite at call site *cp, emit call site data */ static void bbcall(Symbol yycounts, Coordinate* cp, Tree* e) { static Symbol caller; Value v; union coordinate u; Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL); Tree t = *e; defglobal(p, LIT); defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0); defpointer(mkstr(cfunc->name)->u.c.loc); if (IR->little_endian) { u.le.x = cp->x; u.le.y = cp->y; } else { u.be.x = cp->x; u.be.y = cp->y; } (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v)); if (caller == 0) { caller = mksymbol(EXTERN, "_caller", ptr(voidptype)); caller->defined = 0; } if (generic((*e)->op) != CALL) t = (*e)->kids[0]; assert(generic(t->op) == CALL); t = tree(t->op, t->type, tree(RIGHT, t->kids[0]->type, t->kids[0], tree(RIGHT, t->kids[0]->type, asgn(caller, idtree(p)), t->kids[0])), t->kids[1]); if (generic((*e)->op) != CALL) t = tree((*e)->op, (*e)->type, t, (*e)->kids[1]); *e = t; }
/* bbentry - return tree for _prologue(&afunc, &YYlink)' */ static void bbentry(Symbol yylink, Symbol f) { static Symbol prologue; afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL); if (prologue == 0) { prologue = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype)); prologue->defined = 0; } walk(vcall(prologue, voidtype, pointer(idtree(afunc)), pointer(idtree(yylink)), NULL), 0, 0); }
/* stabend - emits the symbol table */ static void stabend(Coordinate *cp, Symbol symroot, Coordinate *cpp[], Symbol sp[], Symbol *ignore) { Symbol addresses; int naddresses, nmodule; { /* annotate top-level symbols */ Symbol p; for (p = symroot; p != NULL; p = up(p->up)) symboluid(p); pickle->globals = symboluid(symroot); } { /* emit addresses of top-level and static symbols */ int i, lc = 0, count = Seq_length(statics); addresses = genident(STATIC, array(voidptype, 1, 0), GLOBAL); comment("addresses:\n"); defglobal(addresses, LIT); for (i = 0; i < count; i++) { Symbol p = Seq_get(statics, i); lc = emit_value(lc, voidptype, p); } lc = pad(maxalign, lc); naddresses = lc; Seq_free(&statics); } { /* emit bp count as an alias for the module */ Symbol spoints = mksymbol(AUTO, stringf("_spoints_V%x_%d", uname, Seq_length(pickle->spoints)), array(unsignedtype, 0, 0)); spoints->generated = 1; defglobal(spoints, LIT); } { /* emit module */ int lc; comment("module:\n"); defglobal(module, LIT); lc = emit_value( 0, unsignedtype, (unsigned long)uname); lc = emit_value(lc, voidptype, addresses); lc = pad(maxalign, lc); nmodule = lc; } Seq_free(&locals); #define printit(x) fprintf(stderr, "%7d " #x "\n", n##x); total += n##x { int total = 0; printit(addresses); printit(module); fprintf(stderr, "%7d bytes total\n", total); } #undef printit { /* complete and write symbol-table pickle */ FILE *f = fopen(stringf("%d.pickle", uname), "wb"); sym_write_module(pickle, f); fclose(f); } }
static void swstmt(int loop, int lab, int lev) { Tree e; struct swtch sw; Code head, tail; t = gettok(); expect('('); definept(NULL); e = expr(')'); if (!isint(e->type)) { error("illegal type `%t' in switch expression\n", e->type); e = retype(e, inttype); } e = cast(e, promote(e->type)); if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op) && e->kids[0]->u.sym->type == e->type && !isvolatile(e->kids[0]->u.sym->type)) { sw.sym = e->kids[0]->u.sym; walk(NULL, 0, 0); } else { sw.sym = genident(REGISTER, e->type, level); addlocal(sw.sym); walk(asgn(sw.sym, e), 0, 0); } head = code(Switch); sw.lab = lab; sw.deflab = NULL; sw.ncases = 0; sw.size = SWSIZE; sw.values = newarray(SWSIZE, sizeof *sw.values, FUNC); sw.labels = newarray(SWSIZE, sizeof *sw.labels, FUNC); refinc /= 10.0; statement(loop, &sw, lev); if (sw.deflab == NULL) { sw.deflab = findlabel(lab); definelab(lab); if (sw.ncases == 0) warning("switch statement with no cases\n"); } if (findlabel(lab + 1)->ref) definelab(lab + 1); tail = codelist; codelist = head->prev; codelist->next = head->prev = NULL; if (sw.ncases > 0) swgen(&sw); branch(lab); head->next->prev = codelist; codelist->next = head->next; codelist = tail; }
/* tracecall - generate code to trace entry to f */ static void tracecall(Symbol printer, Symbol f, void *ignore) { int i; Symbol counter = genident(STATIC, inttype, GLOBAL); defglobal(counter, BSS); (*IR->space)(counter->type->size); frameno = genident(AUTO, inttype, level); addlocal(frameno); appendstr(f->name); appendstr("#"); tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0); appendstr("("); for (i = 0; f->u.f.callee[i]; i++) { if (i) appendstr(","); appendstr(f->u.f.callee[i]->name); appendstr("="); tracevalue(idtree(f->u.f.callee[i]), 0); } if (variadic(f->type)) appendstr(",..."); appendstr(") called\n"); tracefinis(printer); }
Tree condtree(Tree e, Tree l, Tree r) { Symbol t1; Type ty, xty = l->type, yty = r->type; Tree p; if (isarith(xty) && isarith(yty)) ty = binary(xty, yty); else if (eqtype(xty, yty, 1)) ty = unqual(xty); else if (isptr(xty) && isnullptr(r)) ty = xty; else if (isnullptr(l) && isptr(yty)) ty = yty; else if (isptr(xty) && !isfunc(xty->type) && isvoidptr(yty) || isptr(yty) && !isfunc(yty->type) && isvoidptr(xty)) ty = voidptype; else if ((isptr(xty) && isptr(yty) && eqtype(unqual(xty->type), unqual(yty->type), 1))) ty = xty; else { typeerror(COND, l, r); return consttree(0, inttype); } if (isptr(ty)) { ty = unqual(unqual(ty)->type); if (isptr(xty) && isconst(unqual(xty)->type) || isptr(yty) && isconst(unqual(yty)->type)) ty = qual(CONST, ty); if (isptr(xty) && isvolatile(unqual(xty)->type) || isptr(yty) && isvolatile(unqual(yty)->type)) ty = qual(VOLATILE, ty); ty = ptr(ty); } switch (e->op) { case CNST+I: return cast(e->u.v.i != 0 ? l : r, ty); case CNST+U: return cast(e->u.v.u != 0 ? l : r, ty); case CNST+P: return cast(e->u.v.p != 0 ? l : r, ty); case CNST+F: return cast(e->u.v.d != 0.0 ? l : r, ty); } if (ty != voidtype && ty->size > 0) { t1 = genident(REGISTER, unqual(ty), level); /* t1 = temporary(REGISTER, unqual(ty)); */ l = asgn(t1, l); r = asgn(t1, r); } else t1 = NULL; p = tree(COND, ty, cond(e), tree(RIGHT, ty, root(l), root(r))); p->u.sym = t1; return p; }
/* entry_hook - called an function entry */ static void entry_hook(void *cl, Symbol cfunc) { static int nfuncs; Type ty; /* Simulate the declaration of an sframe structure, but without the tag. */ ty = newstruct(STRUCT, ""); #define addfield(name,t) \ ty->size = roundup(ty->size, t->align);\ if (ty->align < t->align) ty->align = t->align; \ newfield(string(name), ty, t)->offset = ty->size; \ ty->size += t->size addfield("up", voidptype); addfield("down", voidptype); addfield("func", inttype); addfield("module",inttype); addfield("ip", inttype); #undef addfield ty->size = roundup(ty->size, ty->align); ty->u.sym->defined = 1; ty->u.sym->generated = 1; tos = genident(AUTO, ty, LOCAL); addlocal(tos); tos->defined = 1; /* Generated the assignments to the shadow frame fields. */ #define set(name,e) walk(asgntree(ASGN,field(lvalue(idtree(tos)),string(#name)),(e)),0,0) set(down, idtree(nub_tos)); set(func, cnsttree(inttype, symboluid(cfunc))); set(module, cnsttree(inttype, uname)); #undef set walk(asgn(nub_tos, lvalue(idtree(tos))), 0, 0); foreach(identifiers, PARAM, setoffset, tos); }
/* * run the makefile for the program to find which objects are necessary */ void fillin_program(prog_t *p) { char path[MAXPATHLEN]; char line[MAXLINELEN]; FILE *f; snprintf(line, MAXLINELEN, "filling in parms for %s", p->name); status(line); if (!p->ident) p->ident = genident(p->name); /* look for the source directory if one wasn't specified by a special */ if (!p->srcdir) { p->srcdir = dir_search(p->name); } /* Determine the actual srcdir (maybe symlinked). */ if (p->srcdir) { snprintf(line, MAXLINELEN, "cd %s && echo -n `/bin/pwd`", p->srcdir); f = popen(line,"r"); if (!f) errx(1, "Can't execute: %s\n", line); path[0] = '\0'; fgets(path, sizeof path, f); if (pclose(f)) errx(1, "Can't execute: %s\n", line); if (!*path) errx(1, "Can't perform pwd on: %s\n", p->srcdir); p->realsrcdir = strdup(path); } /* Unless the option to make object files was specified the * the objects will be built in the source directory unless * an object directory already exists. */ if (!makeobj && !p->objdir && p->srcdir) { char *auto_obj; auto_obj = NULL; snprintf(line, sizeof line, "%s/%s", objprefix, p->realsrcdir); if (is_dir(line) || ((auto_obj = getenv("MK_AUTO_OBJ")) != NULL && strcmp(auto_obj, "yes") == 0)) { if ((p->objdir = strdup(line)) == NULL) out_of_memory(); } else p->objdir = p->realsrcdir; } /* * XXX look for a Makefile.{name} in local directory first. * This lets us override the original Makefile. */ snprintf(path, sizeof(path), "Makefile.%s", p->name); if (is_nonempty_file(path)) { snprintf(line, MAXLINELEN, "Using %s for %s", path, p->name); status(line); } else if (p->srcdir) snprintf(path, sizeof(path), "%s/Makefile", p->srcdir); if (!p->objs && p->srcdir && is_nonempty_file(path)) fillin_program_objs(p, path); if (!p->srcdir && !p->objdir && verbose) warnx("%s: %s: %s", "warning: could not find source directory", infilename, p->name); if (!p->objs && verbose) warnx("%s: %s: warning: could not find any .o files", infilename, p->name); if ((!p->srcdir || !p->objdir) && !p->objs) p->goterror = 1; }
void swcode(Swtch swp, int b[], int lb, int ub) { int hilab, lolab, l, u, k = (lb + ub)/2; long *v = swp->values; if (k > lb && k < ub) { lolab = genlabel(1); hilab = genlabel(1); } else if (k > lb) { lolab = genlabel(1); hilab = swp->deflab->u.l.label; } else if (k < ub) { lolab = swp->deflab->u.l.label; hilab = genlabel(1); } else lolab = hilab = swp->deflab->u.l.label; l = b[k]; u = b[k+1] - 1; if (u - l + 1 <= 3) { int i; for (i = l; i <= u; i++) cmp(EQ, swp->sym, v[i], swp->labels[i]->u.l.label); if (k > lb && k < ub) cmp(GT, swp->sym, v[u], hilab); else if (k > lb) cmp(GT, swp->sym, v[u], hilab); else if (k < ub) cmp(LT, swp->sym, v[l], lolab); else assert(lolab == hilab), branch(lolab); walk(NULL, 0, 0); } else { Tree e; Type ty = signedint(swp->sym->type); Symbol table = genident(STATIC, array(voidptype, u - l + 1, 0), GLOBAL); (*IR->defsymbol)(table); if (!isunsigned(swp->sym->type) || v[l] != 0) cmp(LT, swp->sym, v[l], lolab); cmp(GT, swp->sym, v[u], hilab); e = (*optree['-'])(SUB, cast(idtree(swp->sym), ty), cnsttree(ty, v[l])); if (e->type->size < unsignedptr->size) e = cast(e, unsignedlong); walk(tree(JUMP, voidtype, rvalue((*optree['+'])(ADD, pointer(idtree(table)), e)), NULL), 0, 0); code(Switch); codelist->u.swtch.table = table; codelist->u.swtch.sym = swp->sym; codelist->u.swtch.deflab = swp->deflab; codelist->u.swtch.size = u - l + 1; codelist->u.swtch.values = &v[l]; codelist->u.swtch.labels = &swp->labels[l]; if (v[u] - v[l] + 1 >= 10000) warning("switch generates a huge table\n"); } if (k > lb) { assert(lolab != swp->deflab->u.l.label); definelab(lolab); swcode(swp, b, lb, k - 1); } if (k < ub) { assert(hilab != swp->deflab->u.l.label); definelab(hilab); swcode(swp, b, k + 1, ub); } }
void fillin_program(prog_t * p) { char path[MAXPATHLEN]; char *srcparent; strlst_t *s; int i; snprintf(line, sizeof(line), "filling in parms for %s", p->name); status(line); if (!p->ident) p->ident = genident(p->name); if (!p->srcdir) { srcparent = dir_search(p->name); if (srcparent) snprintf(path, sizeof(path), "%s/%s", srcparent, p->name); if (is_dir(path)) p->srcdir = strdup(path); } if (!p->objdir && p->srcdir) { snprintf(path, sizeof(path), "%s/%s", p->srcdir, objdir); if (is_dir(path)) p->objdir = strdup(path); else { snprintf(path, sizeof(path), "%s/obj.%s", p->srcdir, MACHINE); if (is_dir(path)) p->objdir = strdup(path); else p->objdir = p->srcdir; } } /* We have a sourcedir and no explicit objs, try */ /* to find makefile and get objs from it. */ if (p->srcdir && !p->objs) { for (i = 0; mf_name[i] != NULL; i++) { snprintf(path, sizeof(path), "%s/%s", p->srcdir, mf_name[i]); if (is_nonempty_file(path)) { p->mf_name = mf_name[i]; fillin_program_objs(p, path); break; } } } if (!p->objpaths && p->objdir && p->objs) for (s = p->objs; s != NULL; s = s->next) { snprintf(line, sizeof(line), "%s/%s", p->objdir, s->str); add_string(&p->objpaths, line); } if (!p->srcdir && verbose) fprintf(stderr, "%s: %s: warning: could not find source directory.\n", infilename, p->name); if (!p->objs && verbose) fprintf(stderr, "%s: %s: warning: could not find any .o files.\n", infilename, p->name); if (!p->objpaths) { fprintf(stderr, "%s: %s: error: no objpaths specified or calculated.\n", infilename, p->name); p->goterror = goterror = 1; } }