Coverage Report

Created: 2026-02-26 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jq/src/bytecode.c
Line
Count
Source
1
#include <stdio.h>
2
#include <stdint.h>
3
#include <stdlib.h>
4
5
#include "bytecode.h"
6
#include "jv_alloc.h"
7
8
// flags, length
9
#define NONE 0, 1
10
#define CONSTANT OP_HAS_CONSTANT, 2
11
#define VARIABLE (OP_HAS_VARIABLE | OP_HAS_BINDING), 3
12
#define GLOBAL (OP_HAS_CONSTANT | OP_HAS_VARIABLE | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4
13
#define BRANCH OP_HAS_BRANCH, 2
14
#define CFUNC (OP_HAS_CFUNC | OP_HAS_BINDING), 3
15
#define UFUNC (OP_HAS_UFUNC | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4
16
#define DEFINITION (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0
17
#define CLOSURE_REF_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 2
18
19
#define OP(name, imm, in, out) \
20
  {name, #name, imm, in, out},
21
22
static const struct opcode_description opcode_descriptions[] = {
23
#include "opcode_list.h"
24
};
25
26
static const struct opcode_description invalid_opcode_description = {
27
  -1, "#INVALID", 0, 0, 0, 0
28
};
29
30
31
834M
const struct opcode_description* opcode_describe(opcode op) {
32
834M
  if ((int)op >= 0 && (int)op < NUM_OPCODES) {
33
834M
    return &opcode_descriptions[op];
34
834M
  } else {
35
0
    return &invalid_opcode_description;
36
0
  }
37
834M
}
38
39
40
2.15M
int bytecode_operation_length(uint16_t* codeptr) {
41
2.15M
  int length = opcode_describe(*codeptr)->length;
42
2.15M
  if (*codeptr == CALL_JQ || *codeptr == TAIL_CALL_JQ) {
43
127k
    length += codeptr[1] * 2;
44
127k
  }
45
2.15M
  return length;
46
2.15M
}
47
48
84
static void dump_code(int indent, struct bytecode* bc) {
49
84
  int pc = 0;
50
36.4k
  while (pc < bc->codelen) {
51
36.3k
    printf("%*s", indent, "");
52
36.3k
    dump_operation(bc, bc->code + pc);
53
36.3k
    printf("\n");
54
36.3k
    pc += bytecode_operation_length(bc->code + pc);
55
36.3k
  }
56
84
}
57
58
12.1k
static void symbol_table_free(struct symbol_table* syms) {
59
12.1k
  jv_mem_free(syms->cfunctions);
60
12.1k
  jv_free(syms->cfunc_names);
61
12.1k
  jv_mem_free(syms);
62
12.1k
}
63
64
84
void dump_disassembly(int indent, struct bytecode* bc) {
65
84
  if (bc->nclosures > 0) {
66
10
    printf("%*s[params: ", indent, "");
67
10
    jv params = jv_object_get(jv_copy(bc->debuginfo), jv_string("params"));
68
24
    for (int i=0; i<bc->nclosures; i++) {
69
14
      if (i) printf(", ");
70
14
      jv name = jv_array_get(jv_copy(params), i);
71
14
      printf("%s", jv_string_value(name));
72
14
      jv_free(name);
73
14
    }
74
10
    jv_free(params);
75
10
    printf("]\n");
76
10
  }
77
84
  dump_code(indent, bc);
78
113
  for (int i=0; i<bc->nsubfunctions; i++) {
79
29
    struct bytecode* subfn = bc->subfunctions[i];
80
29
    jv name = jv_object_get(jv_copy(subfn->debuginfo), jv_string("name"));
81
29
    printf("%*s%s:%d:\n", indent, "", jv_string_value(name), i);
82
29
    jv_free(name);
83
29
    dump_disassembly(indent+2, subfn);
84
29
  }
85
84
}
86
87
6.81k
static struct bytecode* getlevel(struct bytecode* bc, int level) {
88
6.84k
  while (level > 0) {
89
25
    bc = bc->parent;
90
25
    level--;
91
25
  }
92
6.81k
  return bc;
93
6.81k
}
94
95
36.3k
void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
96
36.3k
  int pc = codeptr - bc->code;
97
36.3k
  printf("%04d ", pc);
98
36.3k
  const struct opcode_description* op = opcode_describe(bc->code[pc++]);
99
36.3k
  printf("%s", op->name);
100
36.3k
  if (op->length > 1) {
101
22.6k
    uint16_t imm = bc->code[pc++];
102
22.6k
    if (op->op == CALL_JQ || op->op == TAIL_CALL_JQ) {
103
75
      for (int i=0; i<imm+1; i++) {
104
45
        uint16_t level = bc->code[pc++];
105
45
        uint16_t idx = bc->code[pc++];
106
45
        jv name;
107
45
        if (idx & ARG_NEWCLOSURE) {
108
31
          idx &= ~ARG_NEWCLOSURE;
109
31
          name = jv_object_get(jv_copy(getlevel(bc,level)->subfunctions[idx]->debuginfo),
110
31
                               jv_string("name"));
111
31
        } else {
112
14
          name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,level)->debuginfo),
113
14
                                            jv_string("params")), idx);
114
14
        }
115
45
        printf(" %s:%d",
116
45
               jv_string_value(name),
117
45
               idx);
118
45
        jv_free(name);
119
45
        if (level) {
120
21
          printf("^%d", level);
121
21
        }
122
45
      }
123
22.6k
    } else if (op->op == CALL_BUILTIN) {
124
28
      int func = bc->code[pc++];
125
28
      jv name = jv_array_get(jv_copy(bc->globals->cfunc_names), func);
126
28
      printf(" %s", jv_string_value(name));
127
28
      jv_free(name);
128
22.6k
    } else if (op->flags & OP_HAS_BRANCH) {
129
9.02k
      printf(" %04d", pc + imm);
130
13.5k
    } else if (op->flags & OP_HAS_CONSTANT) {
131
6.80k
      printf(" ");
132
6.80k
      jv_dump(jv_array_get(jv_copy(bc->constants), imm), 0);
133
6.80k
    } else if (op->flags & OP_HAS_VARIABLE) {
134
6.77k
      uint16_t v = bc->code[pc++];
135
6.77k
      jv name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,imm)->debuginfo), jv_string("locals")), v);
136
6.77k
      printf(" $%s:%d",
137
6.77k
             jv_string_value(name),
138
6.77k
             v);
139
6.77k
      jv_free(name);
140
6.77k
      if (imm) {
141
1
        printf("^%d", imm);
142
1
      }
143
6.77k
    } else {
144
0
      printf(" %d", imm);
145
0
    }
146
22.6k
  }
147
36.3k
}
148
149
123k
void bytecode_free(struct bytecode* bc) {
150
123k
  if (!bc)
151
937
    return;
152
122k
  jv_mem_free(bc->code);
153
122k
  jv_free(bc->constants);
154
233k
  for (int i=0; i<bc->nsubfunctions; i++)
155
110k
    bytecode_free(bc->subfunctions[i]);
156
122k
  if (!bc->parent)
157
12.1k
    symbol_table_free(bc->globals);
158
122k
  jv_mem_free(bc->subfunctions);
159
122k
  jv_free(bc->debuginfo);
160
122k
  jv_mem_free(bc);
161
122k
}