summaryrefslogtreecommitdiff
path: root/uscript/us_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'uscript/us_debug.c')
-rw-r--r--uscript/us_debug.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/uscript/us_debug.c b/uscript/us_debug.c
new file mode 100644
index 0000000..8d5dfe3
--- /dev/null
+++ b/uscript/us_debug.c
@@ -0,0 +1,117 @@
+#include "us_debug.h"
+
+#include <assert.h>
+
+#include "dyn_arr.h"
+#include "vm.h"
+
+static
+char *bc_names[] = {
+#define BC(name) "BC_" #name,
+#include "xbytecode.h"
+#undef BC
+};
+
+int print_instruction(struct us_proto *proto, int idx)
+{
+ enum bytecode instruction = proto->bytecode[idx];
+ fprintf(stderr, "%04d %-15s ", idx, bc_names[instruction]);
+ switch (instruction) {
+ case BC_LOAD: {
+ int const_idx = proto->bytecode[idx + 1];
+ char *const_str = val_to_str(proto->constants[const_idx], NULL);
+ fprintf(
+ stderr,
+ "%d (%s)\n",
+ const_idx,
+ const_str
+ );
+ mem_free(const_str);
+ return idx + 2;
+ }
+ case BC_LOAD_FUNC: {
+ int const_idx = proto->bytecode[idx + 1];
+ assert(proto->constants[const_idx].type == VAL_PROTO);
+ struct us_proto *p = get_proto(proto->constants[const_idx]);
+ int upvalc = p->upvalc;
+ fprintf(
+ stderr,
+ "%.*s() %d\n",
+ (int)p->name->len, p->name->chars,
+ upvalc
+ );
+ return idx + 2 + upvalc * 2;
+ }
+ case BC_SET_UPVAL:
+ case BC_GET_UPVAL:
+ case BC_SET_LOCAL:
+ case BC_GET_LOCAL: {
+ int local_idx = proto->bytecode[idx + 1];
+ fprintf(
+ stderr,
+ "%d\n",
+ local_idx
+ );
+ return idx + 2;
+ }
+ case BC_CALL:
+ case BC_SMALL_INT: {
+ fprintf(
+ stderr,
+ "%d\n",
+ proto->bytecode[idx + 1]
+ );
+ return idx + 2;
+ }
+ case BC_JMP:
+ case BC_LOOP:
+ case BC_FALSEY_JMP: {
+ u16 jmp = (u16)(proto->bytecode[idx + 1] << 8) | proto->bytecode[idx + 2];
+ int dst = idx + jmp + 3;
+ if (instruction == BC_LOOP) {
+ dst = idx + 3 - jmp;
+ }
+ fprintf(
+ stderr,
+ "-> %04d\n",
+ dst
+ );
+ return idx + 3;
+ }
+ case BC_PRINT:
+ case BC_TRUE:
+ case BC_FALSE:
+ case BC_ZILCH:
+ case BC_POP:
+ case BC_POP_UPVAL:
+ case BC_ADD:
+ case BC_SUB:
+ case BC_MULT:
+ case BC_DIV:
+ case BC_MOD:
+ case BC_NEG:
+ case BC_NOT:
+ case BC_CONCAT:
+ case BC_EQL:
+ case BC_NEQL:
+ case BC_GT:
+ case BC_LT:
+ case BC_GTE:
+ case BC_LTE:
+ case BC_RET:
+ putc('\n', stderr);
+ return idx + 1;
+ }
+
+ // unreachable
+ return idx + 1;
+}
+
+void print_func(struct us_proto *func)
+{
+ fprintf(stderr, "%s():\n", func->name->chars);
+ for (int i = 0; i < da_len(func->bytecode);) {
+ putc('\t', stderr);
+ i = print_instruction(func, i);
+ }
+}