1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-10 10:49:54 +00:00
janet/disasm.c
Calvin Rose 439650f26a Add get and set instructions. GC is still buggy and currently
crashes everything all the time. :(
2017-02-12 21:54:18 -05:00

210 lines
7.0 KiB
C

#include "disasm.h"
/* Width of padded opcode names */
#define OP_WIDTH 20
/* Print various register and arguments to instructions */
static void dasmPrintSlot(FILE * out, uint16_t index) { fprintf(out, "%d ", index); }
static void dasmPrintI16(FILE * out, int16_t number) { fprintf(out, "#%d ", number); }
static void dasmPrintI32(FILE * out, int32_t number) { fprintf(out, "#%d ", number); }
static void dasmPrintF64(FILE * out, double number) { fprintf(out, "#%f ", number); }
static void dasmPrintLiteral(FILE * out, uint16_t index) { fprintf(out, "(%d) ", index); }
static void dasmPrintUpValue(FILE * out, uint16_t level, uint16_t index) {
fprintf(out, "<%d, %d> ", level, index);
}
/* Print the name of the argument but pad it */
static void dasmPrintArg(FILE * out, const char * name) {
uint32_t i = 0;
char c;
while ((c = *name++)) {
fputc(c, out);
++i;
}
for (; i < OP_WIDTH; ++i)
fputc(' ', out);
}
/* Print instructions that take a fixed number of arguments */
static uint32_t dasmPrintFixedOp(FILE * out, const uint16_t * current,
const char * name, uint32_t size) {
uint32_t i;
dasmPrintArg(out, name);
for (i = 1; i <= size; ++i) {
dasmPrintSlot(out, current[i]);
}
return size + 1;
}
/* Print instructions that take a variable number of arguments */
static uint32_t dasmPrintVarArgOp(FILE * out, const uint16_t * current,
const char * name, uint32_t extra) {
uint32_t i, argCount;
dasmPrintArg(out, name);
for (i = 0; i < extra; ++i) {
dasmPrintSlot(out, current[i + 1]);
}
argCount = current[extra + 1];
fprintf(out, ": "); /* Argument separator */
for (i = 0; i < argCount; ++i) {
dasmPrintSlot(out, current[i + extra + 2]);
}
return argCount + extra + 2;
}
/* Print the disassembly for a function definition */
void dasmFuncDef(FILE * out, FuncDef * def) {
dasm(out, def->byteCode, def->byteCodeLen);
}
/* Print the disassembly for a function */
void dasmFunc(FILE * out, Func * f) {
dasm(out, f->def->byteCode, f->def->byteCodeLen);
}
/* Disassemble some bytecode and display it as opcode + arguments assembly */
void dasm(FILE * out, uint16_t *byteCode, uint32_t len) {
uint16_t *current = byteCode;
uint16_t *end = byteCode + len;
fprintf(out, "----- ASM BYTECODE START -----\n");
while (current < end) {
switch (*current) {
case VM_OP_ADD:
current += dasmPrintFixedOp(out, current, "add", 3);
break;
case VM_OP_SUB:
current += dasmPrintFixedOp(out, current, "sub", 3);
break;
case VM_OP_MUL:
current += dasmPrintFixedOp(out, current, "mul", 3);
break;
case VM_OP_DIV:
current += dasmPrintFixedOp(out, current, "div", 3);
break;
case VM_OP_NOT:
current += dasmPrintFixedOp(out, current, "not", 2);
break;
case VM_OP_LD0:
current += dasmPrintFixedOp(out, current, "load0", 1);
break;
case VM_OP_LD1:
current += dasmPrintFixedOp(out, current, "load1", 1);
break;
case VM_OP_FLS:
current += dasmPrintFixedOp(out, current, "loadFalse", 1);
break;
case VM_OP_TRU:
current += dasmPrintFixedOp(out, current, "loadTrue", 1);
break;
case VM_OP_NIL:
current += dasmPrintFixedOp(out, current, "loadNil", 1);
break;
case VM_OP_I16:
dasmPrintArg(out, "loadInt16");
dasmPrintSlot(out, current[1]);
dasmPrintI16(out, ((int16_t *)current)[2]);
current += 3;
break;
case VM_OP_UPV:
dasmPrintArg(out, "loadUpValue");
dasmPrintSlot(out, current[1]);
dasmPrintUpValue(out, current[2], current[3]);
current += 4;
break;
case VM_OP_JIF:
dasmPrintArg(out, "jumpIf");
dasmPrintSlot(out, current[1]);
dasmPrintI32(out, ((int32_t *)(current + 2))[0]);
current += 4;
break;
case VM_OP_JMP:
dasmPrintArg(out, "jump");
dasmPrintI32(out, ((int32_t *)(current + 1))[0]);
current += 3;
break;
case VM_OP_CAL:
current += dasmPrintVarArgOp(out, current, "call", 2);
break;
case VM_OP_RET:
current += dasmPrintFixedOp(out, current, "return", 1);
break;
case VM_OP_SUV:
dasmPrintArg(out, "setUpValue");
dasmPrintSlot(out, current[1]);
dasmPrintUpValue(out, current[2], current[3]);
current += 4;
break;
case VM_OP_CST:
dasmPrintArg(out, "loadLiteral");
dasmPrintSlot(out, current[1]);
dasmPrintLiteral(out, current[2]);
current += 3;
break;
case VM_OP_I32:
dasmPrintArg(out, "loadInt32");
dasmPrintSlot(out, current[1]);
dasmPrintI32(out, ((int32_t *)(current + 2))[0]);
current += 4;
break;
case VM_OP_F64:
dasmPrintArg(out, "loadFloat64");
dasmPrintSlot(out, current[1]);
dasmPrintF64(out, ((double *)(current + 2))[0]);
current += 6;
break;
case VM_OP_MOV:
current += dasmPrintFixedOp(out, current, "move", 2);
break;
case VM_OP_CLN:
dasmPrintArg(out, "makeClosure");
dasmPrintSlot(out, current[1]);
dasmPrintLiteral(out, current[2]);
current += 3;
break;
case VM_OP_EQL:
current += dasmPrintFixedOp(out, current, "equals", 3);
break;
case VM_OP_LTN:
current += dasmPrintFixedOp(out, current, "lessThan", 3);
break;
case VM_OP_LTE:
current += dasmPrintFixedOp(out, current, "lessThanEquals", 3);
break;
case VM_OP_ARR:
current += dasmPrintVarArgOp(out, current, "array", 1);
break;
case VM_OP_DIC:
current += dasmPrintVarArgOp(out, current, "dictionary", 1);
break;
case VM_OP_TCL:
current += dasmPrintVarArgOp(out, current, "tailCall", 1);
break;
case VM_OP_ADM:
current += dasmPrintVarArgOp(out, current, "addMultiple", 1);
break;
case VM_OP_SBM:
current += dasmPrintVarArgOp(out, current, "subMultiple", 1);
break;
case VM_OP_MUM:
current += dasmPrintVarArgOp(out, current, "mulMultiple", 1);
break;
case VM_OP_DVM:
current += dasmPrintVarArgOp(out, current, "divMultiple", 1);
break;
case VM_OP_RTN:
current += dasmPrintFixedOp(out, current, "returnNil", 0);
break;
case VM_OP_GET:
current += dasmPrintFixedOp(out, current, "get", 3);
break;
case VM_OP_SET:
current += dasmPrintFixedOp(out, current, "set", 3);
break;
}
fprintf(out, "\n");
}
fprintf(out, "----- END ASM BYTECODE -----\n");
}