00001 #include "c.h"
00002
00003
00004 static char *fmt, *fp, *fmtend;
00005 static Tree args;
00006 static Symbol frameno;
00007
00008
00009 static void appendstr(char *str) {
00010 do
00011 if (fp == fmtend)
00012 if (fp) {
00013 char *s = allocate(2*(fmtend - fmt), FUNC);
00014 strncpy(s, fmt, fmtend - fmt);
00015 fp = s + (fmtend - fmt);
00016 fmtend = s + 2*(fmtend - fmt);
00017 fmt = s;
00018 } else {
00019 fp = fmt = allocate(80, FUNC);
00020 fmtend = fmt + 80;
00021 }
00022 while ((*fp++ = *str++) != 0);
00023 fp--;
00024 }
00025
00026
00027 static void tracevalue(Tree e, int lev) {
00028 Type ty = unqual(e->type);
00029
00030 switch (ty->op) {
00031 case INT:
00032 if (ty == chartype || ty == signedchar)
00033 appendstr("'\\x%02x'");
00034 else if (ty == longtype)
00035 appendstr("0x%ld");
00036 else
00037 appendstr("0x%d");
00038 break;
00039 case UNSIGNED:
00040 if (ty == chartype || ty == unsignedchar)
00041 appendstr("'\\x%02x'");
00042 else if (ty == unsignedlong)
00043 appendstr("0x%lx");
00044 else
00045 appendstr("0x%x");
00046 break;
00047 case FLOAT:
00048 if (ty == longdouble)
00049 appendstr("%Lg");
00050 else
00051 appendstr("%g");
00052 break;
00053 case POINTER:
00054 if (unqual(ty->type) == chartype
00055 || unqual(ty->type) == signedchar
00056 || unqual(ty->type) == unsignedchar) {
00057 static Symbol null;
00058 if (null == NULL)
00059 null = mkstr("(null)");
00060 tracevalue(cast(e, unsignedtype), lev + 1);
00061 appendstr(" \"%.30s\"");
00062 e = condtree(e, e, pointer(idtree(null->u.c.loc)));
00063 } else {
00064 appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x");
00065 }
00066 break;
00067 case STRUCT: {
00068 Field q;
00069 appendstr("("); appendstr(typestring(ty, "")); appendstr("){");
00070 for (q = ty->u.sym->u.s.flist; q; q = q->link) {
00071 appendstr(q->name); appendstr("=");
00072 tracevalue(field(addrof(e), q->name), lev + 1);
00073 if (q->link)
00074 appendstr(",");
00075 }
00076 appendstr("}");
00077 return;
00078 }
00079 case UNION:
00080 appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}");
00081 return;
00082 case ARRAY:
00083 if (lev && ty->type->size > 0) {
00084 int i;
00085 e = pointer(e);
00086 appendstr("{");
00087 for (i = 0; i < ty->size/ty->type->size; i++) {
00088 Tree p = (*optree['+'])(ADD, e, consttree(i, inttype));
00089 if (isptr(p->type) && isarray(p->type->type))
00090 p = retype(p, p->type->type);
00091 else
00092 p = rvalue(p);
00093 if (i)
00094 appendstr(",");
00095 tracevalue(p, lev + 1);
00096 }
00097 appendstr("}");
00098 } else
00099 appendstr(typestring(ty, ""));
00100 return;
00101 default:
00102 assert(0);
00103 }
00104 e = cast(e, promote(ty));
00105 args = tree(mkop(ARG,e->type), e->type, e, args);
00106 }
00107
00108
00109 static void tracefinis(Symbol printer) {
00110 Tree *ap;
00111 Symbol p;
00112
00113 *fp = 0;
00114 p = mkstr(string(fmt));
00115 for (ap = &args; *ap; ap = &(*ap)->kids[1])
00116 ;
00117 *ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0);
00118 walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0);
00119 args = 0;
00120 fp = fmtend = 0;
00121 }
00122
00123
00124 static void tracecall(Symbol printer, Symbol f) {
00125 int i;
00126 Symbol counter = genident(STATIC, inttype, GLOBAL);
00127
00128 defglobal(counter, BSS);
00129 (*IR->space)(counter->type->size);
00130 frameno = genident(AUTO, inttype, level);
00131 addlocal(frameno);
00132 appendstr(f->name); appendstr("#");
00133 tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0);
00134 appendstr("(");
00135 for (i = 0; f->u.f.callee[i]; i++) {
00136 if (i)
00137 appendstr(",");
00138 appendstr(f->u.f.callee[i]->name); appendstr("=");
00139 tracevalue(idtree(f->u.f.callee[i]), 0);
00140 }
00141 if (variadic(f->type))
00142 appendstr(",...");
00143 appendstr(") called\n");
00144 tracefinis(printer);
00145 }
00146
00147
00148 static void tracereturn(Symbol printer, Symbol f, Tree e) {
00149 appendstr(f->name); appendstr("#");
00150 tracevalue(idtree(frameno), 0);
00151 appendstr(" returned");
00152 if (freturn(f->type) != voidtype && e) {
00153 appendstr(" ");
00154 tracevalue(e, 0);
00155 }
00156 appendstr("\n");
00157 tracefinis(printer);
00158 }
00159
00160
00161 void trace_init(int argc, char *argv[]) {
00162 int i;
00163 static int inited;
00164
00165 if (inited)
00166 return;
00167 inited = 1;
00168 type_init(argc, argv);
00169 if (IR)
00170 for (i = 1; i < argc; i++)
00171 if (strncmp(argv[i], "-t", 2) == 0 && strchr(argv[i], '=') == NULL) {
00172 Symbol printer = mksymbol(EXTERN,
00173 argv[i][2] ? &argv[i][2] : "printf",
00174 ftype(inttype, ptr(qual(CONST, chartype))));
00175 printer->defined = 0;
00176 attach((Apply)tracecall, printer, &events.entry);
00177 attach((Apply)tracereturn, printer, &events.returns);
00178 break;
00179 }
00180 }