trace.c (4602B)
1 #include "c.h" 2 3 4 static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */ 5 static Tree args; /* printf arguments */ 6 static Symbol frameno; /* local holding frame number */ 7 8 /* appendstr - append str to the evolving format string, expanding it if necessary */ 9 static void appendstr(char *str) { 10 do 11 if (fp == fmtend) 12 if (fp) { 13 char *s = allocate(2*(fmtend - fmt), FUNC); 14 strncpy(s, fmt, fmtend - fmt); 15 fp = s + (fmtend - fmt); 16 fmtend = s + 2*(fmtend - fmt); 17 fmt = s; 18 } else { 19 fp = fmt = allocate(80, FUNC); 20 fmtend = fmt + 80; 21 } 22 while ((*fp++ = *str++) != 0); 23 fp--; 24 } 25 26 /* tracevalue - append format and argument to print the value of e */ 27 static void tracevalue(Tree e, int lev) { 28 Type ty = unqual(e->type); 29 30 switch (ty->op) { 31 case INT: 32 if (ty == chartype || ty == signedchar) 33 appendstr("'\\x%02x'"); 34 else if (ty == longtype) 35 appendstr("0x%ld"); 36 else 37 appendstr("0x%d"); 38 break; 39 case UNSIGNED: 40 if (ty == chartype || ty == unsignedchar) 41 appendstr("'\\x%02x'"); 42 else if (ty == unsignedlong) 43 appendstr("0x%lx"); 44 else 45 appendstr("0x%x"); 46 break; 47 case FLOAT: 48 if (ty == longdouble) 49 appendstr("%Lg"); 50 else 51 appendstr("%g"); 52 break; 53 case POINTER: 54 if (unqual(ty->type) == chartype 55 || unqual(ty->type) == signedchar 56 || unqual(ty->type) == unsignedchar) { 57 static Symbol null; 58 if (null == NULL) 59 null = mkstr("(null)"); 60 tracevalue(cast(e, unsignedtype), lev + 1); 61 appendstr(" \"%.30s\""); 62 e = condtree(e, e, pointer(idtree(null->u.c.loc))); 63 } else { 64 appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x"); 65 } 66 break; 67 case STRUCT: { 68 Field q; 69 appendstr("("); appendstr(typestring(ty, "")); appendstr("){"); 70 for (q = ty->u.sym->u.s.flist; q; q = q->link) { 71 appendstr(q->name); appendstr("="); 72 tracevalue(field(addrof(e), q->name), lev + 1); 73 if (q->link) 74 appendstr(","); 75 } 76 appendstr("}"); 77 return; 78 } 79 case UNION: 80 appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}"); 81 return; 82 case ARRAY: 83 if (lev && ty->type->size > 0) { 84 int i; 85 e = pointer(e); 86 appendstr("{"); 87 for (i = 0; i < ty->size/ty->type->size; i++) { 88 Tree p = (*optree['+'])(ADD, e, consttree(i, inttype)); 89 if (isptr(p->type) && isarray(p->type->type)) 90 p = retype(p, p->type->type); 91 else 92 p = rvalue(p); 93 if (i) 94 appendstr(","); 95 tracevalue(p, lev + 1); 96 } 97 appendstr("}"); 98 } else 99 appendstr(typestring(ty, "")); 100 return; 101 default: 102 assert(0); 103 } 104 e = cast(e, promote(ty)); 105 args = tree(mkop(ARG,e->type), e->type, e, args); 106 } 107 108 /* tracefinis - complete & generate the trace call to print */ 109 static void tracefinis(Symbol printer) { 110 Tree *ap; 111 Symbol p; 112 113 *fp = 0; 114 p = mkstr(string(fmt)); 115 for (ap = &args; *ap; ap = &(*ap)->kids[1]) 116 ; 117 *ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0); 118 walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0); 119 args = 0; 120 fp = fmtend = 0; 121 } 122 123 /* tracecall - generate code to trace entry to f */ 124 static void tracecall(Symbol printer, Symbol f) { 125 int i; 126 Symbol counter = genident(STATIC, inttype, GLOBAL); 127 128 defglobal(counter, BSS); 129 (*IR->space)(counter->type->size); 130 frameno = genident(AUTO, inttype, level); 131 addlocal(frameno); 132 appendstr(f->name); appendstr("#"); 133 tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0); 134 appendstr("("); 135 for (i = 0; f->u.f.callee[i]; i++) { 136 if (i) 137 appendstr(","); 138 appendstr(f->u.f.callee[i]->name); appendstr("="); 139 tracevalue(idtree(f->u.f.callee[i]), 0); 140 } 141 if (variadic(f->type)) 142 appendstr(",..."); 143 appendstr(") called\n"); 144 tracefinis(printer); 145 } 146 147 /* tracereturn - generate code to trace return e */ 148 static void tracereturn(Symbol printer, Symbol f, Tree e) { 149 appendstr(f->name); appendstr("#"); 150 tracevalue(idtree(frameno), 0); 151 appendstr(" returned"); 152 if (freturn(f->type) != voidtype && e) { 153 appendstr(" "); 154 tracevalue(e, 0); 155 } 156 appendstr("\n"); 157 tracefinis(printer); 158 } 159 160 /* trace_init - initialize for tracing */ 161 void trace_init(int argc, char *argv[]) { 162 int i; 163 static int inited; 164 165 if (inited) 166 return; 167 inited = 1; 168 type_init(argc, argv); 169 if (IR) 170 for (i = 1; i < argc; i++) 171 if (strncmp(argv[i], "-t", 2) == 0 && strchr(argv[i], '=') == NULL) { 172 Symbol printer = mksymbol(EXTERN, 173 argv[i][2] ? &argv[i][2] : "printf", 174 ftype(inttype, ptr(qual(CONST, chartype)))); 175 printer->defined = 0; 176 attach((Apply)tracecall, printer, &events.entry); 177 attach((Apply)tracereturn, printer, &events.returns); 178 break; 179 } 180 }