prof.c (6387B)
1 #include "c.h" 2 3 4 struct callsite { 5 char *file, *name; 6 union coordinate { 7 unsigned int coord; 8 struct { unsigned int y:16,x:10,index:6; } le; 9 struct { unsigned int index:6,x:10,y:16; } be; 10 } u; 11 }; 12 struct func { 13 struct func *link; 14 struct caller *callers; 15 char *name; 16 union coordinate src; 17 }; 18 struct map { /* source code map; 200 coordinates/map */ 19 int size; 20 union coordinate u[200]; 21 }; 22 23 int npoints; /* # of execution points if -b specified */ 24 int ncalled = -1; /* #times prof.out says current function was called */ 25 static Symbol YYlink; /* symbol for file's struct _bbdata */ 26 static Symbol YYcounts; /* symbol for _YYcounts if -b specified */ 27 static List maplist; /* list of struct map *'s */ 28 static List filelist; /* list of file names */ 29 static Symbol funclist; /* list of struct func *'s */ 30 static Symbol afunc; /* current function's struct func */ 31 32 /* bbcall - build tree to set _callsite at call site *cp, emit call site data */ 33 static void bbcall(Symbol yycounts, Coordinate *cp, Tree *e) { 34 static Symbol caller; 35 Value v; 36 union coordinate u; 37 Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL); 38 Tree t = *e; 39 40 defglobal(p, LIT); 41 defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0); 42 defpointer(mkstr(cfunc->name)->u.c.loc); 43 if (IR->little_endian) { 44 u.le.x = cp->x; 45 u.le.y = cp->y; 46 } else { 47 u.be.x = cp->x; 48 u.be.y = cp->y; 49 } 50 (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v)); 51 if (caller == 0) { 52 caller = mksymbol(EXTERN, "_caller", ptr(voidptype)); 53 caller->defined = 0; 54 } 55 if (generic((*e)->op) != CALL) 56 t = (*e)->kids[0]; 57 assert(generic(t->op) == CALL); 58 t = tree(t->op, t->type, 59 tree(RIGHT, t->kids[0]->type, 60 t->kids[0], 61 tree(RIGHT, t->kids[0]->type, asgn(caller, idtree(p)), t->kids[0])), 62 t->kids[1]); 63 if (generic((*e)->op) != CALL) 64 t = tree((*e)->op, (*e)->type, t, (*e)->kids[1]); 65 *e = t; 66 } 67 68 /* bbentry - return tree for _prologue(&afunc, &YYlink)' */ 69 static void bbentry(Symbol yylink, Symbol f) { 70 static Symbol prologue; 71 72 afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL); 73 if (prologue == 0) { 74 prologue = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype)); 75 prologue->defined = 0; 76 } 77 walk(vcall(prologue, voidtype, pointer(idtree(afunc)), pointer(idtree(yylink)), NULL), 0, 0); 78 79 } 80 81 /* bbexit - return tree for _epilogue(&afunc)' */ 82 static void bbexit(Symbol yylink, Symbol f, Tree e) { 83 static Symbol epilogue; 84 85 if (epilogue == 0) { 86 epilogue = mksymbol(EXTERN, "_epilogue", ftype(inttype, voidptype)); 87 epilogue->defined = 0; 88 } 89 walk(vcall(epilogue, voidtype, pointer(idtree(afunc)), NULL), 0, 0); 90 } 91 92 /* bbfile - add file to list of file names, return its index */ 93 static int bbfile(char *file) { 94 if (file) { 95 List lp; 96 int i = 1; 97 if ((lp = filelist) != NULL) 98 do { 99 lp = lp->link; 100 if (((Symbol)lp->x)->u.c.v.p == file) 101 return i; 102 i++; 103 } while (lp != filelist); 104 filelist = append(mkstr(file), filelist); 105 return i; 106 } 107 return 0; 108 } 109 110 /* bbfunc - emit function name and src coordinates */ 111 static void bbfunc(Symbol yylink, Symbol f) { 112 Value v; 113 union coordinate u; 114 115 defglobal(afunc, DATA); 116 defpointer(funclist); 117 defpointer(NULL); 118 defpointer(mkstr(f->name)->u.c.loc); 119 if (IR->little_endian) { 120 u.le.x = f->u.f.pt.x; 121 u.le.y = f->u.f.pt.y; 122 u.le.index = bbfile(f->u.f.pt.file); 123 } else { 124 u.be.x = f->u.f.pt.x; 125 u.be.y = f->u.f.pt.y; 126 u.be.index = bbfile(f->u.f.pt.file); 127 } 128 (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v)); 129 funclist = afunc; 130 } 131 132 /* bbincr - build tree to increment execution point at *cp */ 133 static void bbincr(Symbol yycounts, Coordinate *cp, Tree *e) { 134 struct map *mp = maplist->x; 135 Tree t; 136 137 /* append *cp to source map */ 138 if (mp->size >= NELEMS(mp->u)) { 139 NEW(mp, PERM); 140 mp->size = 0; 141 maplist = append(mp, maplist); 142 } 143 if (IR->little_endian) { 144 mp->u[mp->size].le.x = cp->x; 145 mp->u[mp->size].le.y = cp->y; 146 mp->u[mp->size++].le.index = bbfile(cp->file); 147 } else { 148 mp->u[mp->size].be.x = cp->x; 149 mp->u[mp->size].be.y = cp->y; 150 mp->u[mp->size++].be.index = bbfile(cp->file); 151 } 152 t = incr('+', rvalue((*optree['+'])(ADD, pointer(idtree(yycounts)), 153 consttree(npoints++, inttype))), consttree(1, inttype)); 154 if (*e) 155 *e = tree(RIGHT, (*e)->type, t, *e); 156 else 157 *e = t; 158 } 159 160 /* bbvars - emit definition for basic block counting data */ 161 static void bbvars(Symbol yylink) { 162 int i, j, n = npoints; 163 Value v; 164 struct map **mp; 165 Symbol coords, files, *p; 166 167 if (!YYcounts && !yylink) 168 return; 169 if (YYcounts) { 170 if (n <= 0) 171 n = 1; 172 YYcounts->type = array(unsignedtype, n, 0); 173 defglobal(YYcounts, BSS); 174 } 175 files = genident(STATIC, array(charptype, 1, 0), GLOBAL); 176 defglobal(files, LIT); 177 for (p = ltov(&filelist, PERM); *p; p++) 178 defpointer((*p)->u.c.loc); 179 defpointer(NULL); 180 coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL); 181 defglobal(coords, LIT); 182 for (i = n, mp = ltov(&maplist, PERM); *mp; i -= (*mp)->size, mp++) 183 for (j = 0; j < (*mp)->size; j++) 184 (*IR->defconst)(U, unsignedtype->size, (v.u = (*mp)->u[j].coord, v)); 185 if (i > 0) 186 (*IR->space)(i*coords->type->type->size); 187 defpointer(NULL); 188 defglobal(yylink, DATA); 189 defpointer(NULL); 190 (*IR->defconst)(U, unsignedtype->size, (v.u = n, v)); 191 defpointer(YYcounts); 192 defpointer(coords); 193 defpointer(files); 194 defpointer(funclist); 195 } 196 197 /* profInit - initialize basic block profiling options */ 198 void prof_init(int argc, char *argv[]) { 199 int i; 200 static int inited; 201 202 if (inited) 203 return; 204 inited = 1; 205 type_init(argc, argv); 206 if (IR) 207 for (i = 1; i < argc; i++) 208 if (strncmp(argv[i], "-a", 2) == 0) { 209 if (ncalled == -1 210 && process(argv[i][2] ? &argv[i][2] : "prof.out") > 0) 211 ncalled = 0; 212 } else if ((strcmp(argv[i], "-b") == 0 213 || strcmp(argv[i], "-C") == 0) && YYlink == 0) { 214 YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); 215 attach((Apply)bbentry, YYlink, &events.entry); 216 attach((Apply)bbexit, YYlink, &events.returns); 217 attach((Apply)bbfunc, YYlink, &events.exit); 218 attach((Apply)bbvars, YYlink, &events.end); 219 if (strcmp(argv[i], "-b") == 0) { 220 YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); 221 maplist = append(allocate(sizeof (struct map), PERM), maplist); 222 ((struct map *)maplist->x)->size = 0; 223 attach((Apply)bbcall, YYcounts, &events.calls); 224 attach((Apply)bbincr, YYcounts, &events.points); 225 } 226 } 227 }