diff options
author | Stephen Dolan <mu@netsoc.tcd.ie> | 2012-09-18 17:44:43 +0100 |
---|---|---|
committer | Stephen Dolan <mu@netsoc.tcd.ie> | 2012-09-18 17:44:43 +0100 |
commit | a4eea165bbab6d13f89b59707e835d58b7014a66 (patch) | |
tree | b99ee5dde8540f8dbe5de3d87b99e04ac4dd2673 /bytecode.c | |
parent | 25cbab056b1f73e96b636c88779a92400d92dc15 (diff) |
Move everything around - delete old Haskell code, clean up build.
Diffstat (limited to 'bytecode.c')
-rw-r--r-- | bytecode.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/bytecode.c b/bytecode.c new file mode 100644 index 00000000..bafd0474 --- /dev/null +++ b/bytecode.c @@ -0,0 +1,88 @@ +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +#include "bytecode.h" +#include "opcode.h" + +static int bytecode_operation_length(uint16_t* codeptr) { + if (opcode_describe(*codeptr)->flags & OP_HAS_VARIABLE_LENGTH_ARGLIST) { + return 2 + codeptr[1] * 2; + } else { + return opcode_length(*codeptr); + } +} + +void dump_disassembly(int indent, struct bytecode* bc) { + if (bc->nclosures > 0) { + printf("%*s[params: %d]\n", indent, "", bc->nclosures); + } + dump_code(indent, bc); + for (int i=0; i<bc->nsubfunctions; i++) { + printf("%*ssubfn[%d]:\n", indent, "", i); + dump_disassembly(indent+2, bc->subfunctions[i]); + } +} + +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); + } +} + +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->flags & OP_HAS_VARIABLE_LENGTH_ARGLIST) { + for (int i=0; i<imm; i++) { + uint16_t level = bc->code[pc++]; + uint16_t idx = bc->code[pc++]; + if (idx & ARG_NEWCLOSURE) { + printf(" subfn[%d]", idx & ~ARG_NEWCLOSURE); + } else { + printf(" param[%d]", idx); + } + if (level) { + printf("^%d", level); + } + } + } 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++]; + printf(" v%d", v); + if (imm) { + printf("^%d", imm); + } + } else { + printf(" %d", imm); + } + } +} + +void symbol_table_free(struct symbol_table* syms) { + free(syms->cfunctions); + free(syms); +} + +void bytecode_free(struct bytecode* bc) { + 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); + free(bc->subfunctions); + free(bc); +} |