@ 261102.1

150823.1 · 0c93eb3379241dc4775718a9d39f54a6c4de20d6

Move source files to src/

reading declarations

Changes to src/bytecode.c. All files

src/bytecode.c

new file mode 100644@@ -0,0 +1,161 @@+#include <stdio.h>+#include <stdint.h>+#include <stdlib.h>++#include "bytecode.h"+#include "jv_alloc.h"++// flags, length+#define NONE 0, 1+#define CONSTANT OP_HAS_CONSTANT, 2+#define VARIABLE (OP_HAS_VARIABLE | OP_HAS_BINDING), 3+#define GLOBAL (OP_HAS_CONSTANT | OP_HAS_VARIABLE | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4+#define BRANCH OP_HAS_BRANCH, 2+#define CFUNC (OP_HAS_CFUNC | OP_HAS_BINDING), 3+#define UFUNC (OP_HAS_UFUNC | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4+#define DEFINITION (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0+#define CLOSURE_REF_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 2++#define OP(name, imm, in, out) \+  {name, #name, imm, in, out},++static const struct opcode_description opcode_descriptions[] = {+#include "opcode_list.h"+};++static const struct opcode_description invalid_opcode_description = {+  -1, "#INVALID", 0, 0, 0, 0+};+++const struct opcode_description* opcode_describe(opcode op) {+  if ((int)op >= 0 && (int)op < NUM_OPCODES) {+    return &opcode_descriptions[op];+  } else {+    return &invalid_opcode_description;+  }+}+++int bytecode_operation_length(uint16_t* codeptr) {+  int length = opcode_describe(*codeptr)->length;+  if (*codeptr == CALL_JQ || *codeptr == TAIL_CALL_JQ) {+    length += codeptr[1] * 2;+  }+  return length;+}++static void dump_code(int indent, struct bytecode* bc) {+  int pc = 0;+  while (pc < bc->codelen) {+    printf("%*s", indent, "");+    dump_operation(bc, bc->code + pc);+    printf("\n");+    pc += bytecode_operation_length(bc->code + pc);+  }+}++static void symbol_table_free(struct symbol_table* syms) {+  jv_mem_free(syms->cfunctions);+  jv_free(syms->cfunc_names);+  jv_mem_free(syms);+}++void dump_disassembly(int indent, struct bytecode* bc) {+  if (bc->nclosures > 0) {+    printf("%*s[params: ", indent, "");+    jv params = jv_object_get(jv_copy(bc->debuginfo), jv_string("params"));+    for (int i=0; i<bc->nclosures; i++) {+      if (i) printf(", ");+      jv name = jv_array_get(jv_copy(params), i);+      printf("%s", jv_string_value(name));+      jv_free(name);+    }+    jv_free(params);+    printf("]\n");+  }+  dump_code(indent, bc);+  for (int i=0; i<bc->nsubfunctions; i++) {+    struct bytecode* subfn = bc->subfunctions[i];+    jv name = jv_object_get(jv_copy(subfn->debuginfo), jv_string("name"));+    printf("%*s%s:%d:\n", indent, "", jv_string_value(name), i);+    jv_free(name);+    dump_disassembly(indent+2, subfn);+  }+}++static struct bytecode* getlevel(struct bytecode* bc, int level) {+  while (level > 0) {+    bc = bc->parent;+    level--;+  }+  return bc;+}++void dump_operation(struct bytecode* bc, uint16_t* codeptr) {+  int pc = codeptr - bc->code;+  printf("%04d ", pc);+  const struct opcode_description* op = opcode_describe(bc->code[pc++]);+  printf("%s", op->name);+  if (op->length > 1) {+    uint16_t imm = bc->code[pc++];+    if (op->op == CALL_JQ || op->op == TAIL_CALL_JQ) {+      for (int i=0; i<imm+1; i++) {+        uint16_t level = bc->code[pc++];+        uint16_t idx = bc->code[pc++];+        jv name;+        if (idx & ARG_NEWCLOSURE) {+          idx &= ~ARG_NEWCLOSURE;+          name = jv_object_get(jv_copy(getlevel(bc,level)->subfunctions[idx]->debuginfo),+                               jv_string("name"));+        } else {+          name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,level)->debuginfo),+                                            jv_string("params")), idx);+        }+        printf(" %s:%d",+               jv_string_value(name),+               idx);+        jv_free(name);+        if (level) {+          printf("^%d", level);+        }+      }+    } else if (op->op == CALL_BUILTIN) {+      int func = bc->code[pc++];+      jv name = jv_array_get(jv_copy(bc->globals->cfunc_names), func);+      printf(" %s", jv_string_value(name));+      jv_free(name);+    } else if (op->flags & OP_HAS_BRANCH) {+      printf(" %04d", pc + imm);+    } else if (op->flags & OP_HAS_CONSTANT) {+      printf(" ");+      jv_dump(jv_array_get(jv_copy(bc->constants), imm), 0);+    } else if (op->flags & OP_HAS_VARIABLE) {+      uint16_t v = bc->code[pc++];+      jv name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,imm)->debuginfo), jv_string("locals")), v);+      printf(" $%s:%d",+             jv_string_value(name),+             v);+      jv_free(name);+      if (imm) {+        printf("^%d", imm);+      }+    } else {+      printf(" %d", imm);+    }+  }+}++void bytecode_free(struct bytecode* bc) {+  if (!bc)+    return;+  jv_mem_free(bc->code);+  jv_free(bc->constants);+  for (int i=0; i<bc->nsubfunctions; i++)+    bytecode_free(bc->subfunctions[i]);+  if (!bc->parent)+    symbol_table_free(bc->globals);+  jv_mem_free(bc->subfunctions);+  jv_free(bc->debuginfo);+  jv_mem_free(bc);+}