# ifndef FUNCDEF # include "kfun.h" # include "control.h" # include "table.h" # endif # ifdef DUMP_FUNCS # ifndef FUNCDEF static void showclass(class) register short class; { if (class & C_COMPILED) printf("compiled "); if (class & C_TYPECHECKED) printf("typechecked "); if (class & C_UNDEFINED) printf("undefined "); if (class & C_VARARGS) printf("varargs "); if (class & C_PRIVATE) printf("private "); if (class & C_STATIC) printf("static "); if (class & C_NOMASK) printf("nomask "); } static void show_proto(func, proto) char *func, *proto; { int i; showclass(PROTO_CLASS(proto)); printf("%s %s(", i_typename(PROTO_FTYPE(proto)), func); for (i = 0; i < PROTO_NARGS(proto) - 1; i++) { printf("%s, ", i_typename(PROTO_ARGS(proto)[i])); } if (i < PROTO_NARGS(proto)) { printf("%s", i_typename(PROTO_ARGS(proto)[i] & ~T_ELLIPSIS)); if (PROTO_ARGS(proto)[i] & T_ELLIPSIS) { printf("..."); } } putchar(')'); } static void showctrl(ctrl) control *ctrl; { register unsigned short i; printf("inherits:\n"); for (i = 0; i < ctrl->ninherits; i++) { printf(" %s (%u, %u)\n", ctrl->inherits[i].obj->chain.name, ctrl->inherits[i].funcoffset, ctrl->inherits[i].varoffset); } printf("progsize: %lu\n", (unsigned long) ctrl->progsize); if (ctrl->nstrings > 0) { printf("string constants:\n"); for (i = 0; i < ctrl->nstrings; i++) { printf("%3u: \"%s\"\n", i, d_get_strconst(ctrl, ctrl->ninherits - 1, i)->text); } } if (ctrl->nfuncdefs > 0) { d_get_funcdefs(ctrl); printf("function definitions:\n"); for (i = 0; i < ctrl->nfuncdefs; i++) { printf("%3u: %04lx ", i, (unsigned long) ctrl->funcdefs[i].offset); show_proto(d_get_strconst(ctrl, ctrl->funcdefs[i].inherit, ctrl->funcdefs[i].index)->text, d_get_prog(ctrl) + ctrl->funcdefs[i].offset); putchar('\n'); } } if (ctrl->nvardefs > 0) { d_get_vardefs(ctrl); printf("variable definitions:\n"); for (i = 0; i < ctrl->nvardefs; i++) { printf("%3u: ", i); showclass(ctrl->vardefs[i].class); printf("%s %s\n", i_typename(ctrl->vardefs[i].type), d_get_strconst(ctrl, ctrl->vardefs[i].inherit, ctrl->vardefs[i].index)->text); } } if (ctrl->nfuncalls > 0) { d_get_funcalls(ctrl); printf("funcalls:\n"); for (i = 0; i < ctrl->nfuncalls; i++) { control *c2; dfuncdef *f; c2 = ctrl->inherits[UCHAR(ctrl->funcalls[2 * i])].obj->ctrl; f = d_get_funcdefs(c2) + UCHAR(ctrl->funcalls[2 * i + 1]); printf("%3u: %s(%d, %d)\n", i, d_get_strconst(c2, f->inherit, f->index)->text, UCHAR(ctrl->funcalls[2 * i]), UCHAR(ctrl->funcalls[2 * i + 1])); } } if (ctrl->nsymbols > 0) { d_get_symbols(ctrl); printf("symbols:\n"); for (i = 0; i < ctrl->nsymbols; i++) { control *c2; dfuncdef *f; char *name; printf("%3u: (%u) ", i, ctrl->symbols[i].next); c2 = ctrl->inherits[UCHAR(ctrl->symbols[i].inherit)].obj->ctrl; f = d_get_funcdefs(c2) + UCHAR(ctrl->symbols[i].index); name = d_get_strconst(c2, f->inherit, f->index)->text; show_proto(name, d_get_prog(c2) + f->offset); putchar('\n'); } } printf("%u variables, %u floats, %u floatdefs\n", ctrl->nvariables, ctrl->nfloats, ctrl->nfloatdefs); } static unsigned short addr; static unsigned short line; static unsigned short newline; static char *code; static bool pop; static int codesize; static void show_instr(s) char *s; { register int size; printf("%04x\t", addr); if (line != newline) { line = newline; printf("%4u\t", line); } else { putchar('\t'); } size = codesize; if (size > 4) { size = 4; } switch (size) { case 0: printf("\t "); break; case 1: printf("%02x\t ", UCHAR(code[0])); break; case 2: printf("%02x %02x\t ", UCHAR(code[0]), UCHAR(code[1])); break; case 3: printf("%02x %02x %02x ", UCHAR(code[0]), UCHAR(code[1]), UCHAR(code[2])); break; case 4: printf("%02x %02x %02x %02x ", UCHAR(code[0]), UCHAR(code[1]), UCHAR(code[2]), UCHAR(code[3])); break; } addr += size; code += size; codesize -= size; if (pop) { printf("P\t"); } else { putchar('\t'); } pop = FALSE; if (s != (char *) NULL) { printf("%s", s); } putchar('\n'); fflush(stdout); } void disasm(ctrl, func) control *ctrl; int func; { char *pc, *end, *linenumbers, buffer[1000]; control *cc; register unsigned short u, u2, u3; register unsigned long l; unsigned short a, progsize; int sz; xfloat flt; char fltbuf[18]; pc = d_get_prog(ctrl) + d_get_funcdefs(ctrl)[func].offset; show_proto(d_get_strconst(ctrl, ctrl->funcdefs[func].inherit, ctrl->funcdefs[func].index)->text, pc); u2 = PROTO_CLASS(pc) & C_COMPILED; pc += PROTO_SIZE(pc); printf("; depth %u,", FETCH2U(pc, u)); printf(" %u local vars\n", FETCH1U(pc)); if (u2) { return; } progsize = FETCH2U(pc, u); end = linenumbers = pc + progsize; addr = 0; line = 0; newline = 0; printf("addr\tline\tcode\t pop instruction\n"); while (pc < end) { code = pc; pop = *code & I_POP_BIT; if (((*code & I_LINE_MASK) >> I_LINE_SHIFT) <= 2) { newline += (*code & I_LINE_MASK) >> I_LINE_SHIFT; } else { u = FETCH1U(linenumbers); if (u & 128) { newline += u - 128 - 64; } else { u = (u << 8) | FETCH1U(linenumbers); newline += u - 16384; } } switch (FETCH1U(pc) & I_INSTR_MASK) { case I_PUSH_ZERO: codesize = 1; show_instr("PUSH_ZERO"); break; case I_PUSH_ONE: codesize = 1; show_instr("PUSH_ONE"); break; case I_PUSH_INT1: codesize = 2; sprintf(buffer, "PUSH_INT1 %d", FETCH1S(pc)); show_instr(buffer); break; case I_PUSH_INT4: codesize = 5; sprintf(buffer, "PUSH_INT4 %ld", FETCH4S(pc, l)); show_instr(buffer); break; case I_PUSH_FLOAT: codesize = 7; flt.high = FETCH2U(pc, u); flt.low = FETCH4U(pc, l); flt_ftoa(&flt, fltbuf); sprintf(buffer, "PUSH_FLOAT6 %s", fltbuf); show_instr(buffer); break; case I_PUSH_STRING: codesize = 2; u = FETCH1U(pc); sprintf(buffer, "PUSH_STRING \"%s\"", d_get_strconst(ctrl, ctrl->ninherits - 1, u)->text); show_instr(buffer); break; case I_PUSH_NEAR_STRING: codesize = 3; u = FETCH1U(pc); u2 = FETCH1U(pc); sprintf(buffer, "PUSH_NEAR_STRING \"%s\"", d_get_strconst(ctrl, u, u2)->text); show_instr(buffer); break; case I_PUSH_FAR_STRING: codesize = 4; u = FETCH1U(pc); FETCH2U(pc, u2); sprintf(buffer, "PUSH_FAR_STRING \"%s\"", d_get_strconst(ctrl, u, u2)->text); show_instr(buffer); break; case I_PUSH_LOCAL: codesize = 2; sprintf(buffer, "PUSH_LOCAL %d", FETCH1S(pc)); show_instr(buffer); break; case I_PUSH_GLOBAL: codesize = 2; u = FETCH1U(pc); d_get_vardefs(ctrl); sprintf(buffer, "PUSH_GLOBAL %s", d_get_strconst(ctrl, ctrl->vardefs[u].inherit, ctrl->vardefs[u].index)->text); show_instr(buffer); break; case I_PUSH_FAR_GLOBAL: codesize = 3; u = FETCH1U(pc); u2 = FETCH1U(pc); cc = ctrl->inherits[u].obj->ctrl; d_get_vardefs(cc); sprintf(buffer, "PUSH_FAR_GLOBAL %s", d_get_strconst(cc, cc->vardefs[u2].inherit, cc->vardefs[u2].index)->text); show_instr(buffer); break; case I_PUSH_LOCAL_LVAL: if (pop) { pop = 0; codesize = 3; u = FETCH1S(pc); sprintf(buffer, "PUSH_LOCAL_LVALUE %d (%s)", (short) u, i_typename(FETCH1U(pc))); } else { codesize = 2; sprintf(buffer, "PUSH_LOCAL_LVALUE %d", FETCH1S(pc)); } show_instr(buffer); break; case I_PUSH_GLOBAL_LVAL: if (pop) { pop = 0; codesize = 3; u = FETCH1U(pc); d_get_vardefs(ctrl); sprintf(buffer, "PUSH_GLOBAL_LVALUE %s (%s)", d_get_strconst(ctrl, ctrl->vardefs[u].inherit, ctrl->vardefs[u].index)->text, i_typename(FETCH1U(pc))); } else { codesize = 2; u = FETCH1U(pc); d_get_vardefs(ctrl); sprintf(buffer, "PUSH_GLOBAL_LVALUE %s", d_get_strconst(ctrl, ctrl->vardefs[u].inherit, ctrl->vardefs[u].index)->text); } show_instr(buffer); break; case I_PUSH_FAR_GLOBAL_LVAL: if (pop) { pop = 0; codesize = 4; u = FETCH1U(pc); u2 = FETCH1U(pc); cc = ctrl->inherits[u].obj->ctrl; d_get_vardefs(cc); sprintf(buffer, "PUSH_FAR_GLOBAL_LVALUE %s (%s)", d_get_strconst(cc, cc->vardefs[u2].inherit, cc->vardefs[u2].index)->text, i_typename(FETCH1U(pc))); } else { codesize = 3; u = FETCH1U(pc); u2 = FETCH1U(pc); cc = ctrl->inherits[u].obj->ctrl; d_get_vardefs(cc); sprintf(buffer, "PUSH_FAR_GLOBAL_LVALUE %s", d_get_strconst(cc, cc->vardefs[u2].inherit, cc->vardefs[u2].index)->text); } show_instr(buffer); break; case I_INDEX: codesize = 1; show_instr("INDEX"); break; case I_INDEX_LVAL: if (pop) { pop = 0; codesize = 2; sprintf(buffer, "INDEX_LVALUE (%s)", i_typename(FETCH1U(pc))); show_instr(buffer); } else { codesize = 1; show_instr("INDEX_LVALUE"); } break; case I_AGGREGATE: codesize = 4; u = FETCH1U(pc); sprintf(buffer, "AGGREGATE %s %u", (u) ? "map" : "array", FETCH2U(pc, u2)); show_instr(buffer); break; case I_SPREAD: if (pop) { pop = 0; codesize = 3; u = FETCH1S(pc); sprintf(buffer, "SPREAD %u (%s)", u, i_typename(FETCH1U(pc))); } else { codesize = 2; sprintf(buffer, "SPREAD %u", FETCH1S(pc)); } show_instr(buffer); break; case I_CAST: codesize = 2; sprintf(buffer, "CAST %s", i_typename(FETCH1U(pc))); show_instr(buffer); break; case I_FETCH: codesize = 1; show_instr("FETCH"); break; case I_STORE: codesize = 1; show_instr("STORE"); break; case I_JUMP: codesize = 3; sprintf(buffer, "JUMP %04x", FETCH2U(pc, u)); show_instr(buffer); break; case I_JUMP_ZERO: codesize = 3; sprintf(buffer, "JUMP_ZERO %04x", FETCH2U(pc, u)); show_instr(buffer); break; case I_JUMP_NONZERO: codesize = 3; sprintf(buffer, "JUMP_NONZERO %04x", FETCH2U(pc, u)); show_instr(buffer); break; case I_SWITCH: switch (FETCH1U(pc)) { case 0: codesize = 4; FETCH2U(pc, u); sz = FETCH1U(pc); sprintf(buffer, "SWITCH INT %u", u); show_instr(buffer); codesize = --u * (sz + 2) + 3; a = addr + 1; sprintf(buffer, " DEFAULT: %04x", FETCH2U(pc, u2)); show_instr(buffer); a += 2; while (u > 0) { long l; switch (sz) { case 4: FETCH4S(pc, l); break; case 3: FETCH3S(pc, l); break; case 2: FETCH2S(pc, l); break; case 1: l = FETCH1S(pc); break; } sprintf(buffer, " CASE %ld: %04x", l, FETCH2U(pc, u2)); show_instr(buffer); a += 2 + sz; --u; } break; case 1: codesize = 4; FETCH2U(pc, u); sz = FETCH1U(pc); sprintf(buffer, "SWITCH RANGE %u", u); show_instr(buffer); codesize = --u * (2 * sz + 2) + 3; a = addr + 1; sprintf(buffer, " DEFAULT: %04x", FETCH2U(pc, u2)); show_instr(buffer); a += 2; while (u > 0) { register long h; switch (sz) { case 4: FETCH4S(pc, l); break; case 3: FETCH3S(pc, l); break; case 2: FETCH2S(pc, l); break; case 1: l = FETCH1S(pc); break; } switch (sz) { case 4: FETCH4S(pc, h); break; case 3: FETCH3S(pc, h); break; case 2: FETCH2S(pc, h); break; case 1: h = FETCH1S(pc); break; } sprintf(buffer, " CASE %ld .. %ld: %04x", l, h, FETCH2U(pc, u2)); show_instr(buffer); a += 2 + sz * 2; --u; } break; case 2: codesize = 4; FETCH2U(pc, u); sprintf(buffer, "SWITCH STR %u", u); show_instr(buffer); codesize = --u * 5 + 3; a = addr; sprintf(buffer, " DEFAULT: %04x", FETCH2U(pc, u2)); show_instr(buffer); a += 3; if (FETCH1U(pc) == 0) { codesize -= 3; sprintf(buffer, " CASE 0: %04x", FETCH2U(pc, u2)); show_instr(buffer); a += 2; --u; } while (u > 0) { string *str; int i; i = FETCH1U(pc); str = d_get_strconst(ctrl, i, FETCH2S(pc, u2)); sprintf(buffer, " CASE \"%s\": %04x", str->text, FETCH2U(pc, u2)); show_instr(buffer); a += 5; --u; } break; } break; case I_CALL_KFUNC: u = FETCH1U(pc); if (PROTO_CLASS(KFUN(u).proto) & C_VARARGS) { codesize = 3; u2 = FETCH1U(pc); } else { codesize = 2; u2 = PROTO_NARGS(KFUN(u).proto); } sprintf(buffer, "CALL_KFUNC %s%s %u", KFUN(u).name, (PROTO_CLASS(KFUN(u).proto) & C_TYPECHECKED) ? " (tc)" : "", u2); show_instr(buffer); break; case I_CALL_AFUNC: codesize = 3; u = FETCH1U(pc); cc = ctrl->inherits[0].obj->ctrl; d_get_funcdefs(cc); sprintf(buffer, "CALL_AFUNC %s %u", d_get_strconst(cc, cc->funcdefs[u].inherit, cc->funcdefs[u].index)->text, FETCH1U(pc)); show_instr(buffer); break; case I_CALL_DFUNC: codesize = 4; u = FETCH1U(pc); u2 = FETCH1U(pc); cc = ctrl->inherits[u].obj->ctrl; d_get_funcdefs(cc); sprintf(buffer, "CALL_DFUNC [%u] %s %u", u2, d_get_strconst(cc, cc->funcdefs[u2].inherit, cc->funcdefs[u2].index)->text, FETCH1U(pc)); show_instr(buffer); break; case I_CALL_FUNC: codesize = 4; FETCH2U(pc, u); u += ctrl->inherits[ctrl->ninherits - 1].funcoffset; u2 = d_get_funcalls(ctrl)[2 * u]; u3 = ctrl->funcalls[2 * u + 1]; cc = ctrl->inherits[u2].obj->ctrl; d_get_funcdefs(cc); sprintf(buffer, "CALL_FUNC [%u] %s %u", u2, d_get_strconst(cc, cc->funcdefs[u3].inherit, cc->funcdefs[u3].index)->text, FETCH1U(pc)); show_instr(buffer); break; case I_CATCH: codesize = 3; sprintf(buffer, "CATCH %04x", FETCH2U(pc, u)); show_instr(buffer); break; case I_RLIMITS: codesize = 2; sprintf(buffer, "RLIMITS%s", (!FETCH1U(pc)) ? " (checked)" : ""); show_instr(buffer); break; case I_RETURN: codesize = 1; show_instr("RETURN"); break; default: addr += 1; codesize = 0; printf("unknown instruction %d\n", *code & I_INSTR_MASK); break; } while (codesize > 0) { show_instr((char *) NULL); } } } # endif # ifdef FUNCDEF FUNCDEF("dump_object", kf_dump_object, pt_dump_object) # else char pt_dump_object[] = { C_TYPECHECKED | C_STATIC, T_VOID, 1, T_OBJECT }; int kf_dump_object(f) frame *f; { showctrl(o_control(&otable[f->sp->oindex])); fflush(stdout); return 0; } # endif # ifdef FUNCDEF FUNCDEF("dump_function", kf_dump_function, pt_dump_function) # else char pt_dump_function[] = { C_TYPECHECKED | C_STATIC, T_VOID, 2, T_OBJECT, T_STRING }; int kf_dump_function(f) frame *f; { dsymbol *symb; symb = ctrl_symb(o_control(&otable[f->sp[1].oindex]), f->sp->u.string->text, f->sp->u.string->len); if (symb != (dsymbol *) NULL) { control *ctrl; ctrl = o_control(&otable[f->sp[1].oindex]); disasm(o_control(ctrl->inherits[UCHAR(symb->inherit)].obj), UCHAR(symb->index)); fflush(stdout); } str_del((f->sp++)->u.string); return 0; } # endif # endif /* DUMP_FUNCS */