1
0
mirror of https://github.com/stedolan/jq.git synced 2024-05-11 05:55:39 +00:00
stedolan-jq/c/bytecode.c

89 lines
2.3 KiB
C
Raw Normal View History

2012-08-16 01:00:30 +01:00
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
2012-08-16 01:00:30 +01:00
#include "bytecode.h"
#include "opcode.h"
2012-08-21 18:14:13 +01:00
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) {
2012-08-26 14:25:56 +01:00
if (bc->nclosures > 0) {
printf("%*s[params: %d]\n", indent, "", bc->nclosures);
}
2012-08-21 18:14:13 +01:00
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) {
2012-08-16 01:00:30 +01:00
int pc = 0;
while (pc < bc->codelen) {
2012-08-21 18:14:13 +01:00
printf("%*s", indent, "");
2012-08-16 01:00:30 +01:00
dump_operation(bc, bc->code + pc);
printf("\n");
2012-08-21 18:14:13 +01:00
pc += bytecode_operation_length(bc->code + pc);
2012-08-16 01:00:30 +01:00
}
}
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) {
2012-08-16 01:00:30 +01:00
uint16_t imm = bc->code[pc++];
2012-08-21 18:14:13 +01:00
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);
2012-08-16 01:00:30 +01:00
} else if (op->flags & OP_HAS_CONSTANT) {
2012-08-21 18:24:38 +01:00
printf(" ");
jv_dump(jv_array_get(jv_copy(bc->constants), imm));
2012-08-16 01:00:30 +01:00
} else if (op->flags & OP_HAS_VARIABLE) {
2012-08-21 18:24:38 +01:00
uint16_t v = bc->code[pc++];
printf(" v%d", v);
if (imm) {
printf("^%d", imm);
}
2012-08-16 01:00:30 +01:00
} else {
2012-08-21 18:14:13 +01:00
printf(" %d", imm);
2012-08-16 01:00:30 +01:00
}
}
}
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);
}