2020-10-28 05:16:30 +00:00
|
|
|
#include "cdebug.h"
|
|
|
|
#include "cvalue.h"
|
|
|
|
#include "cobj.h"
|
|
|
|
|
|
|
|
void printIndent(int indent) {
|
|
|
|
for (int i = 0; i < indent; i++)
|
|
|
|
printf("\t");
|
|
|
|
}
|
|
|
|
|
|
|
|
int simpleInstruction(const char *name, int offset) {
|
|
|
|
printf("%s", name);
|
|
|
|
return offset + 1; // consume opcode
|
|
|
|
}
|
|
|
|
|
2020-11-19 20:41:21 +00:00
|
|
|
int u8OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
2020-10-28 05:16:30 +00:00
|
|
|
printf("%-16s [%03d]", name, readu8Chunk(chunk, offset + 1));
|
|
|
|
return offset + 2;
|
|
|
|
}
|
|
|
|
|
2020-11-19 20:41:21 +00:00
|
|
|
int u16OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
2020-10-28 05:16:30 +00:00
|
|
|
printf("%-16s [%05d]", name, readu16Chunk(chunk, offset + 1));
|
|
|
|
return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION));
|
|
|
|
}
|
|
|
|
|
2020-11-19 20:41:21 +00:00
|
|
|
int u8u8OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
|
|
|
printf("%-16s [%03d] [%03d]", name, readu8Chunk(chunk, offset + 1), readu8Chunk(chunk, offset + 2));
|
|
|
|
return offset + 3; // op + u8 + u8
|
|
|
|
}
|
|
|
|
|
|
|
|
int u8u16OperandInstruction(const char *name, CChunk *chunk, int offset) {
|
|
|
|
printf("%-16s [%03d] [%05d]", name, readu8Chunk(chunk, offset + 1), readu16Chunk(chunk, offset + 2));
|
|
|
|
return offset + 4; // op + u8 + u16
|
|
|
|
}
|
|
|
|
|
2020-10-28 05:16:30 +00:00
|
|
|
int constInstruction(const char *name, CChunk *chunk, int offset, int indent) {
|
|
|
|
int index = readu16Chunk(chunk, offset + 1);
|
|
|
|
printf("%-16s [%05d] - ", name, index);
|
|
|
|
CValue val = chunk->constants.values[index];
|
|
|
|
|
|
|
|
printValue(val);
|
|
|
|
|
|
|
|
return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION)); // consume opcode + uint
|
|
|
|
}
|
|
|
|
|
|
|
|
// public methods in the cdebug.h header
|
|
|
|
|
|
|
|
void disasmChunk(CChunk *chunk, const char *name, int indent) {
|
|
|
|
printIndent(indent);
|
|
|
|
printf("===[[ %s ]]===\n", name);
|
|
|
|
|
|
|
|
for (int offset = 0; offset < chunk->count;) {
|
|
|
|
offset = disasmInstr(chunk, offset, indent);
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int disasmInstr(CChunk *chunk, int offset, int indent) {
|
|
|
|
printIndent(indent);
|
|
|
|
printf("%04d ", offset);
|
|
|
|
|
|
|
|
INSTRUCTION i = chunk->buf[offset];
|
|
|
|
int line = chunk->lineInfo[offset];
|
|
|
|
|
|
|
|
if (offset > 0 && line == chunk->lineInfo[offset - 1]) {
|
|
|
|
printf(" | ");
|
|
|
|
} else {
|
|
|
|
printf("%4d ", line);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
case OP_LOADCONST:
|
|
|
|
return constInstruction("OP_LOADCONST", chunk, offset, indent);
|
|
|
|
case OP_SETGLOBAL:
|
|
|
|
return constInstruction("OP_SETGLOBAL", chunk, offset, indent);
|
|
|
|
case OP_GETGLOBAL:
|
|
|
|
return constInstruction("OP_GETGLOBAL", chunk, offset, indent);
|
|
|
|
case OP_SETLOCAL:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u8OperandInstruction("OP_SETLOCAL", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_GETLOCAL:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u8OperandInstruction("OP_GETLOCAL", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_SETUPVAL:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u8OperandInstruction("OP_SETUPVAL", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_GETUPVAL:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u8OperandInstruction("OP_GETUPVAL", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_PEJMP:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u16OperandInstruction("OP_PEJMP", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_EJMP:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u16OperandInstruction("OP_EJMP", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_JMP:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u16OperandInstruction("OP_JMP", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_JMPBACK:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u16OperandInstruction("OP_JMPBACK", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_POP:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u8OperandInstruction("OP_POP", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_CALL:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u8OperandInstruction("OP_CALL", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_CLOSURE: {
|
|
|
|
int index = readu16Chunk(chunk, offset + 1);
|
|
|
|
printf("%-16s [%05d] - ", "OP_CLOSURE", index);
|
|
|
|
CValue val = chunk->constants.values[index];
|
|
|
|
CObjFunction *cobjFunc = (CObjFunction*)val.val.obj;
|
|
|
|
offset += 3; // we consumed the opcode + u16
|
|
|
|
|
|
|
|
printValue(val);
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
// list the upvalues/locals that are captured
|
|
|
|
for (int i = 0; i < cobjFunc->upvals; i++) {
|
|
|
|
uint8_t encoding = readu8Chunk(chunk, offset++);
|
|
|
|
uint8_t index = readu8Chunk(chunk, offset++);
|
|
|
|
printIndent(indent + 1);
|
|
|
|
printf("references %s [%d]\n", encoding == OP_GETLOCAL ? "local" : "upvalue", index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// print the chunk
|
|
|
|
disasmChunk(&cobjFunc->chunk, cobjFunc->name == NULL ? UNNAMEDCHUNK : cobjFunc->name->str, indent+1);
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
case OP_CLOSE:
|
|
|
|
return simpleInstruction("OP_CLOSE", offset);
|
2020-11-04 04:10:51 +00:00
|
|
|
case OP_NEWOBJECT:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u16OperandInstruction("OP_NEWOBJECT", chunk, offset);
|
2020-11-04 04:10:51 +00:00
|
|
|
case OP_GETOBJECT:
|
|
|
|
return simpleInstruction("OP_GETOBJECT", offset);
|
|
|
|
case OP_SETOBJECT:
|
|
|
|
return simpleInstruction("OP_SETOBJECT", offset);
|
2020-11-13 23:39:47 +00:00
|
|
|
case OP_INVOKE:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u8OperandInstruction("OP_INVOKE", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_ADD:
|
|
|
|
return simpleInstruction("OP_ADD", offset);
|
|
|
|
case OP_SUB:
|
|
|
|
return simpleInstruction("OP_SUB", offset);
|
|
|
|
case OP_MULT:
|
|
|
|
return simpleInstruction("OP_MULT", offset);
|
|
|
|
case OP_DIV:
|
|
|
|
return simpleInstruction("OP_DIV", offset);
|
|
|
|
case OP_TRUE:
|
|
|
|
return simpleInstruction("OP_TRUE", offset);
|
|
|
|
case OP_FALSE:
|
|
|
|
return simpleInstruction("OP_FALSE", offset);
|
|
|
|
case OP_NIL:
|
|
|
|
return simpleInstruction("OP_NIL", offset);
|
|
|
|
case OP_NOT:
|
|
|
|
return simpleInstruction("OP_NOT", offset);
|
|
|
|
case OP_EQUAL:
|
|
|
|
return simpleInstruction("OP_EQUAL", offset);
|
|
|
|
case OP_GREATER:
|
|
|
|
return simpleInstruction("OP_GREATER", offset);
|
|
|
|
case OP_GREATER_EQUAL:
|
|
|
|
return simpleInstruction("OP_GREATER_EQUAL", offset);
|
|
|
|
case OP_LESS:
|
|
|
|
return simpleInstruction("OP_LESS", offset);
|
|
|
|
case OP_LESS_EQUAL:
|
|
|
|
return simpleInstruction("OP_LESS_EQUAL", offset);
|
|
|
|
case OP_NEGATE:
|
|
|
|
return simpleInstruction("OP_NEGATE", offset);
|
|
|
|
case OP_CONCAT:
|
2020-11-19 20:41:21 +00:00
|
|
|
return u8OperandInstruction("OP_CONCAT", chunk, offset);
|
|
|
|
case OP_INCLOCAL:
|
|
|
|
return u8u8OperandInstruction("OP_INCLOCAL", chunk, offset);
|
|
|
|
case OP_INCGLOBAL:
|
|
|
|
return u8u16OperandInstruction("OP_INCGLOBAL", chunk, offset);
|
|
|
|
case OP_INCUPVAL:
|
|
|
|
return u8u8OperandInstruction("OP_INCLOCAL", chunk, offset);
|
|
|
|
case OP_INCOBJECT:
|
|
|
|
return u8u16OperandInstruction("OP_INCOBJECT", chunk, offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
case OP_RETURN:
|
2020-11-10 01:44:12 +00:00
|
|
|
return simpleInstruction("OP_RETURN", offset);
|
2020-10-28 05:16:30 +00:00
|
|
|
default:
|
|
|
|
printf("Unknown opcode! [%d]\n", i);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|