diff options
Diffstat (limited to 'dis.c')
-rw-r--r-- | dis.c | 170 |
1 files changed, 98 insertions, 72 deletions
@@ -10,90 +10,116 @@ static void print_const(Chunk *ch, uint8_t ix) { println_val(k); } +static void disasm_chunk_h(Chunk *ch, int depth); void disasm_chunk(Chunk *ch) { - puts("constants:"); + disasm_chunk_h(ch, 0); +} + +static size_t disasm_instr_h(Chunk *ch, size_t ip, int depth); +size_t disasm_instr(Chunk *ch, size_t ip) { + return disasm_instr_h(ch, ip, 0); +} + + +static size_t disasm_instr_h(Chunk *ch, size_t ip, int depth) { + size_t orig_ip = ip; + uint8_t instr = ch->bc.d[ip]; + printf("%*s%04zd\t",depth,"",ip); + ip ++; + switch (instr) { + case OP_LOADK: { + uint8_t ix = ch->bc.d[ip++]; + printf("loadk #%d\t; ",ix); + print_const(ch, ix); + break; + } + case OP_GETGLOBAL: { + uint8_t ix = ch->bc.d[ip++]; + printf("getglobal #%d\t; ",ix); + print_const(ch, ix); + break; + } + case OP_SETGLOBAL: { + uint8_t ix = ch->bc.d[ip++]; + printf("setglobal #%d\t; ",ix); + print_const(ch, ix); + break; + } + case OP_CALL: { + uint8_t nargs = ch->bc.d[ip++]; + printf("call #%hhu\n",nargs); + break; + } + #define RSHORT() (uint16_t)( ch->bc.d[ip-2] | ch->bc.d[ip-1] << 8 ) + case OP_SKIP: { + ip += 2; + uint16_t offset = RSHORT(); + printf("skip +%5hu\t; -> %04zd\n", offset, ip + offset); + break; + } + case OP_0BRANCH: { + ip += 2; + uint16_t offset = RSHORT(); + printf("0branch +%5hu\t; -> %04zd\n", offset, ip + offset); + break; + } + case OP_REDO: { + ip += 2; + uint16_t offset = RSHORT(); + printf("redo -%5hu\t; -> %04zd\n", offset, ip - offset); + break; + } + #undef RSHORT + + #define SIMPLE_INSTR(opcode, str) \ + case opcode: puts(str); break; + SIMPLE_INSTR(OP_RET, "ret") + SIMPLE_INSTR(OP_PUTS, "puts") + SIMPLE_INSTR(OP_PRINT, "print") + SIMPLE_INSTR(OP_DROP, "drop") + SIMPLE_INSTR(OP_ADD, "add") + SIMPLE_INSTR(OP_SUB, "sub") + SIMPLE_INSTR(OP_MUL, "mul") + SIMPLE_INSTR(OP_DIV, "div") + SIMPLE_INSTR(OP_MOD, "mod") + SIMPLE_INSTR(OP_NIL, "nil") + SIMPLE_INSTR(OP_TRUE, "true") + SIMPLE_INSTR(OP_FALSE, "false") + SIMPLE_INSTR(OP_CMP, "cmp") + SIMPLE_INSTR(OP_EQU, "equ") + SIMPLE_INSTR(OP_HALT, "halt") + #undef SIMPLE_INSTR + + default: + printf("unknown opcode %d\n", instr); + exit(2); + + } + + return ip - orig_ip; + +} + +static void disasm_chunk_h(Chunk *ch, int depth) { + #define P(msg) printf("%*s%s\n",depth,"",msg); + P("constants:"); for (uint8_t cix = 0; cix < ch->consts.len; cix++) { - printf("%hd\t",cix); + printf("%*s%hd\t",depth,"",cix); print_const(ch, cix); } - puts("bytecode:"); + P("bytecode:"); + #undef P for (size_t ip = 0; ip < ch->bc.len; ) { - uint8_t instr = ch->bc.d[ip]; - printf("%04zd\t",ip); - ip ++; - switch (instr) { - case OP_LOADK: { - uint8_t ix = ch->bc.d[ip++]; - printf("loadk #%d\t; ",ix); - print_const(ch, ix); - break; - } - case OP_GETGLOBAL: { - uint8_t ix = ch->bc.d[ip++]; - printf("getglobal #%d\t; ",ix); - print_const(ch, ix); - break; - } - case OP_SETGLOBAL: { - uint8_t ix = ch->bc.d[ip++]; - printf("setglobal #%d\t; ",ix); - print_const(ch, ix); - break; - } - #define RSHORT() (uint16_t)( ch->bc.d[ip-2] | ch->bc.d[ip-1] << 8 ) - case OP_SKIP: { - ip += 2; - uint16_t offset = RSHORT(); - printf("skip +%5hu\t; -> %04zd\n", offset, ip + offset); - break; - } - case OP_0BRANCH: { - ip += 2; - uint16_t offset = RSHORT(); - printf("0branch +%5hu\t; -> %04zd\n", offset, ip + offset); - break; - } - case OP_REDO: { - ip += 2; - uint16_t offset = RSHORT(); - printf("redo -%5hu\t; -> %04zd\n", offset, ip - offset); - break; - } - #undef RSHORT - - -#define SIMPLE_INSTR(opcode, str) \ - case opcode: puts(str); break; - SIMPLE_INSTR(OP_RET, "ret") - SIMPLE_INSTR(OP_PUTS, "puts") - SIMPLE_INSTR(OP_PRINT, "print") - SIMPLE_INSTR(OP_DROP, "drop") - SIMPLE_INSTR(OP_ADD, "add") - SIMPLE_INSTR(OP_SUB, "sub") - SIMPLE_INSTR(OP_MUL, "mul") - SIMPLE_INSTR(OP_DIV, "div") - SIMPLE_INSTR(OP_MOD, "mod") - SIMPLE_INSTR(OP_NIL, "nil") - SIMPLE_INSTR(OP_TRUE, "true") - SIMPLE_INSTR(OP_FALSE, "false") - SIMPLE_INSTR(OP_CMP, "cmp") - SIMPLE_INSTR(OP_EQU, "equ") -#undef SIMPLE_INSTR - - default: - printf("unknown opcode %d\n", instr); - exit(2); - - } + ip += disasm_instr_h(ch, ip, depth); } printf("\n"); for (uint8_t cix = 0; cix < ch->consts.len; cix++) { Val c = ch->consts.d[cix]; if (IS_FUNC(c)) { - printf("const %d is function:\n", cix); - disasm_chunk(&AS_FUNC(c)->chunk); + printf("%*sconst %d is function:\n",depth,"", cix); + disasm_chunk_h(&AS_FUNC(c)->ch,depth+4); } } |