1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#include <stdlib.h>
#include <assert.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "bcode.h"
enum bcode_insn {
END,
#include "gen/enum.inc"
};
static void append(struct compile_state *cs, enum bcode_insn label, breg_t imm)
{
assert(cs->labels);
if (cs->pc == cs->size) {
cs->size *= 2;
/* better memory checks could be a good idea */
void *p = realloc(cs->s.op, cs->size * sizeof(*cs->s.op));
assert(p);
p = realloc(cs->s.imm, cs->size * sizeof(*cs->s.imm));
assert(p);
}
struct run_state *s = &cs->s;
s->op[cs->pc] = cs->labels[label];
s->imm[cs->pc] = imm;
cs->pc++;
}
#define RELOC cs->pc
#define PUSH_OP(label) append(cs, label, (breg_t){ .g = 0 })
#define PUSH_IMM_OP(label, imm) append(cs, label, (breg_t){ .g = imm })
#define PUSH_DIMM_OP(label, dimm) append(cs, label, (breg_t){ .f = dimm })
#include "gen/select.inc"
#include "gen/macro.inc"
#define IMM s.imm[pc].g
#define DIMM s.imm[pc].f
#define NEXT_INSN goto *s.op[pc++]
#define JUMP(i) goto *s.op[pc = (i)]
static gbreg_t _run(struct compile_state *cs, bool init)
{
static void *labels[] = {
[END] = &&end,
#include "gen/static.inc"
};
if (init) {
cs->labels = labels;
return 0;
}
#include "gen/head.inc"
#include "gen/regs.inc"
const struct run_state s = cs->s;
size_t pc = 0;
JUMP(pc);
#include "gen/body.inc"
end: /* we assume there's always at least one general register */
return r0;
}
gbreg_t run(struct compile_state *cs)
{
return _run(cs, false);
}
void init(struct compile_state *cs)
{
cs->labels = NULL;
cs->s.imm = NULL;
cs->s.op = NULL;
cs->size = 0;
cs->pc = 0;
_run(cs, true);
}
void destroy(struct compile_state *cs)
{
free(cs->s.op);
free(cs->s.imm);
}
|