source tracking and composite primitives
This commit is contained in:
parent
b9a5bc5e63
commit
aebe586a05
9 changed files with 237 additions and 220 deletions
272
src/debug.c
272
src/debug.c
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "chunk.h"
|
||||
#include "debug.h"
|
||||
#include "dictionary.h"
|
||||
#include "print.h"
|
||||
|
|
@ -21,177 +22,146 @@ static I decode_sleb128(U8 *ptr, Z *bytes_read) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static Z dis_instr(Bc *chunk, Z offset, Dt **dictionary, I indent);
|
||||
|
||||
static V dis(Bc *chunk, Dt **dictionary, I indent) {
|
||||
Z offset = 0;
|
||||
while (offset < chunk->count)
|
||||
offset = dis_instr(chunk, offset, dictionary, indent);
|
||||
}
|
||||
|
||||
V disassemble(Bc *chunk, const char *name, Dt **dictionary) {
|
||||
printf("=== %s ===\n", name);
|
||||
Z offset = 0;
|
||||
while (offset < chunk->count) {
|
||||
offset = disassemble_instruction(chunk, offset, dictionary);
|
||||
}
|
||||
dis(chunk, dictionary, 0);
|
||||
}
|
||||
|
||||
Z disassemble_instruction(Bc *chunk, Z offset, Dt **dictionary) {
|
||||
static Z dis_instr(Bc *chunk, Z offset, Dt **dictionary, I indent) {
|
||||
for (I i = 0; i < indent * 2; i++)
|
||||
putchar(' ');
|
||||
fflush(stdout);
|
||||
printf("%04zu ", offset);
|
||||
U8 opcode = chunk->items[offset++];
|
||||
|
||||
#define CASE(name) case OP_##name:
|
||||
#define SIMPLE(name) \
|
||||
case OP_##name: \
|
||||
printf(#name "\n"); \
|
||||
return offset;
|
||||
|
||||
switch (opcode) {
|
||||
case OP_NOP:
|
||||
printf("NOP\n");
|
||||
return offset;
|
||||
case OP_NIL:
|
||||
printf("NIL\n");
|
||||
return offset;
|
||||
case OP_CONST: {
|
||||
Z bytes_read;
|
||||
I idx = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("CONST %ld", idx);
|
||||
if (idx >= 0 && idx < (I)chunk->constants.count) {
|
||||
O obj = chunk->constants.items[idx];
|
||||
printf(" (");
|
||||
print(obj);
|
||||
printf(")");
|
||||
SIMPLE(NOP);
|
||||
SIMPLE(NIL);
|
||||
CASE(CONST) {
|
||||
Z bytes_read;
|
||||
I idx = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("CONST %ld", idx);
|
||||
if (idx >= 0 && idx < (I)chunk->constants.count) {
|
||||
O obj = chunk->constants.items[idx];
|
||||
printf(" (");
|
||||
print(obj);
|
||||
printf(")");
|
||||
|
||||
// If it's a quotation, disassemble it inline
|
||||
if (!IMM(obj) && obj != NIL && type(obj) == TYPE_QUOT) {
|
||||
Hd *hdr = UNBOX(obj);
|
||||
Bc **chunk_ptr = (Bc **)(hdr + 1);
|
||||
Bc *quot_chunk = *chunk_ptr;
|
||||
printf("\n");
|
||||
|
||||
// Disassemble quotation with indentation
|
||||
for (Z i = 0; i < quot_chunk->count; ) {
|
||||
printf(" ");
|
||||
i = disassemble_instruction(quot_chunk, i, dictionary);
|
||||
if (!IMM(obj) && obj != NIL && type(obj) == TYPE_QUOT) {
|
||||
putchar('\n');
|
||||
Hd *hdr = UNBOX(obj);
|
||||
Bc **chunk_ptr = (Bc **)(hdr + 1);
|
||||
Bc *quot_chunk = *chunk_ptr;
|
||||
dis(quot_chunk, dictionary, indent + 1);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
return offset + bytes_read;
|
||||
}
|
||||
printf("\n");
|
||||
return offset + bytes_read;
|
||||
}
|
||||
printf("\n");
|
||||
return offset + bytes_read;
|
||||
}
|
||||
case OP_DROP: {
|
||||
printf("DROP\n");
|
||||
return offset;
|
||||
}
|
||||
case OP_DUP: {
|
||||
printf("DUP\n");
|
||||
return offset;
|
||||
}
|
||||
case OP_SWAP: {
|
||||
printf("SWAP\n");
|
||||
return offset;
|
||||
}
|
||||
case OP_TOR:
|
||||
printf("TOR\n");
|
||||
return offset;
|
||||
case OP_FROMR:
|
||||
printf("FROMR\n");
|
||||
return offset;
|
||||
case OP_JUMP: {
|
||||
Z bytes_read;
|
||||
I ofs = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("JUMP %ld -> %zu\n", ofs, offset + bytes_read + ofs);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
case OP_JUMP_IF_NIL: {
|
||||
Z bytes_read;
|
||||
I ofs = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("JUMP_IF_NIL %ld -> %zu\n", ofs, offset + bytes_read + ofs);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
case OP_CALL: {
|
||||
Z bytes_read;
|
||||
I ofs = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("CALL %ld\n", ofs);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
case OP_DOWORD: {
|
||||
Z bytes_read;
|
||||
I hash = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("DOWORD");
|
||||
SIMPLE(DROP);
|
||||
SIMPLE(DUP);
|
||||
SIMPLE(SWAP);
|
||||
SIMPLE(NIP);
|
||||
SIMPLE(OVER);
|
||||
SIMPLE(BURY);
|
||||
SIMPLE(DIG);
|
||||
SIMPLE(TOR);
|
||||
SIMPLE(FROMR);
|
||||
CASE(JUMP) {
|
||||
Z bytes_read;
|
||||
I ofs = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("JUMP %ld -> %zu\n", ofs, offset + bytes_read + ofs);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
CASE(JUMP_IF_NIL) {
|
||||
Z bytes_read;
|
||||
I ofs = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("JUMP_IF_NIL %ld -> %zu\n", ofs, offset + bytes_read + ofs);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
CASE(CALL) {
|
||||
Z bytes_read;
|
||||
I ofs = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("CALL %ld\n", ofs);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
CASE(DOWORD) {
|
||||
Z bytes_read;
|
||||
I hash = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("DOWORD");
|
||||
|
||||
if (dictionary && *dictionary) {
|
||||
Dt *entry = lookup_hash(dictionary, hash);
|
||||
if (entry != NULL) {
|
||||
printf(" %s", entry->name);
|
||||
if (dictionary && *dictionary) {
|
||||
Dt *entry = lookup_hash(dictionary, hash);
|
||||
if (entry != NULL) {
|
||||
printf(" %s", entry->name);
|
||||
} else {
|
||||
printf(" ???");
|
||||
}
|
||||
} else {
|
||||
printf(" ???");
|
||||
printf(" 0x%lx", hash);
|
||||
}
|
||||
} else {
|
||||
printf(" 0x%lx", hash);
|
||||
printf("\n");
|
||||
return offset + bytes_read;
|
||||
}
|
||||
printf("\n");
|
||||
return offset + bytes_read;
|
||||
}
|
||||
case OP_APPLY:
|
||||
printf("APPLY\n");
|
||||
return offset;
|
||||
case OP_TAIL_CALL: {
|
||||
Z bytes_read;
|
||||
I ofs = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("TAIL_CALL %ld\n", ofs);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
case OP_TAIL_DOWORD: {
|
||||
Z bytes_read;
|
||||
I hash = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("TAIL_DOWORD");
|
||||
SIMPLE(APPLY);
|
||||
CASE(TAIL_CALL) {
|
||||
Z bytes_read;
|
||||
I ofs = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("TAIL_CALL %ld\n", ofs);
|
||||
return offset + bytes_read;
|
||||
}
|
||||
CASE(TAIL_DOWORD) {
|
||||
Z bytes_read;
|
||||
I hash = decode_sleb128(&chunk->items[offset], &bytes_read);
|
||||
printf("TAIL_DOWORD");
|
||||
|
||||
if (dictionary && *dictionary) {
|
||||
Dt *entry = lookup_hash(dictionary, hash);
|
||||
if (entry != NULL) {
|
||||
printf(" %s", entry->name);
|
||||
if (dictionary && *dictionary) {
|
||||
Dt *entry = lookup_hash(dictionary, hash);
|
||||
if (entry != NULL) {
|
||||
printf(" %s", entry->name);
|
||||
} else {
|
||||
printf(" ???");
|
||||
}
|
||||
} else {
|
||||
printf(" ???");
|
||||
printf(" 0x%lx", hash);
|
||||
}
|
||||
} else {
|
||||
printf(" 0x%lx", hash);
|
||||
printf("\n");
|
||||
return offset + bytes_read;
|
||||
}
|
||||
printf("\n");
|
||||
return offset + bytes_read;
|
||||
}
|
||||
case OP_TAIL_APPLY:
|
||||
printf("TAIL_APPLY\n");
|
||||
return offset;
|
||||
case OP_RETURN:
|
||||
printf("RETURN\n");
|
||||
return offset;
|
||||
case OP_CHOOSE:
|
||||
printf("CHOOSE\n");
|
||||
return offset;
|
||||
case OP_ADD:
|
||||
printf("ADD\n");
|
||||
return offset;
|
||||
case OP_SUB:
|
||||
printf("SUB\n");
|
||||
return offset;
|
||||
case OP_MUL:
|
||||
printf("MUL\n");
|
||||
return offset;
|
||||
case OP_DIV:
|
||||
printf("DIV\n");
|
||||
return offset;
|
||||
case OP_MOD:
|
||||
printf("MOD\n");
|
||||
return offset;
|
||||
case OP_EQ:
|
||||
printf("EQ\n");
|
||||
return offset;
|
||||
case OP_NEQ:
|
||||
printf("NEQ\n");
|
||||
return offset;
|
||||
case OP_LT:
|
||||
printf("LT\n");
|
||||
return offset;
|
||||
case OP_GT:
|
||||
printf("GT\n");
|
||||
return offset;
|
||||
case OP_LTE:
|
||||
printf("LTE\n");
|
||||
return offset;
|
||||
case OP_GTE:
|
||||
printf("GTE\n");
|
||||
return offset;
|
||||
SIMPLE(TAIL_APPLY);
|
||||
SIMPLE(RETURN);
|
||||
SIMPLE(CHOOSE);
|
||||
SIMPLE(ADD);
|
||||
SIMPLE(SUB);
|
||||
SIMPLE(MUL);
|
||||
SIMPLE(DIV);
|
||||
SIMPLE(MOD);
|
||||
SIMPLE(EQ);
|
||||
SIMPLE(NEQ);
|
||||
SIMPLE(LT);
|
||||
SIMPLE(GT);
|
||||
SIMPLE(LTE);
|
||||
SIMPLE(GTE);
|
||||
default:
|
||||
printf("? (%d)\n", opcode);
|
||||
printf("??? (%d)\n", opcode);
|
||||
return offset;
|
||||
}
|
||||
|
||||
#undef SIMPLE
|
||||
#undef CASE
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue