summaryrefslogtreecommitdiff
path: root/dis.c
diff options
context:
space:
mode:
Diffstat (limited to 'dis.c')
-rw-r--r--dis.c170
1 files changed, 98 insertions, 72 deletions
diff --git a/dis.c b/dis.c
index 5097b05..0b22ac3 100644
--- a/dis.c
+++ b/dis.c
@@ -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);
}
}