/
bf_compiler.v
132 lines (118 loc) · 2.91 KB
/
bf_compiler.v
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import os
import wasm
const runtime_page = 1024 * 64 // 64 KiBs
fn generate_ciovec(mut start wasm.Function, sp wasm.LocalIndex) {
// construct struct __wasi_ciovec_t
//
// field, `const uint8_t *buf`
start.i32_const(runtime_page)
start.local_get(sp)
start.store(.i32_t, 2, 0)
// field, `__wasi_size_t buf_len`
start.i32_const(runtime_page)
start.i32_const(1) // len
start.store(.i32_t, 2, 4)
}
fn generate_code(mut start wasm.Function, bf_expr string) {
// locals are initialised to zero, by spec
sp := start.new_local_named(.i32_t, 'sp')
mut loop_labels := []wasm.LabelIndex{}
mut block_labels := []wasm.LabelIndex{}
// our page, the second one
for ch in bf_expr {
match ch {
`>` {
start.local_get(sp)
start.i32_const(1)
start.add(.i32_t)
start.local_set(sp)
}
`<` {
start.local_get(sp)
start.i32_const(1)
start.sub(.i32_t)
start.local_set(sp)
}
`+` {
start.local_get(sp)
{
start.local_get(sp)
start.load8(.i32_t, false, 0, 0)
start.i32_const(1)
start.add(.i32_t)
}
start.store8(.i32_t, 0, 0)
}
`-` {
start.local_get(sp)
{
start.local_get(sp)
start.load8(.i32_t, false, 0, 0)
start.i32_const(1)
start.sub(.i32_t)
}
start.store8(.i32_t, 0, 0)
}
`.` {
generate_ciovec(mut start, sp)
start.i32_const(1) // stdout
start.i32_const(runtime_page) // *iovs
start.i32_const(1) // iovs_len
start.i32_const(runtime_page + 1024) // *nwritten
start.call_import('wasi_unstable', 'fd_write')
start.drop() // ignore errno
}
`,` {
generate_ciovec(mut start, sp)
start.i32_const(0) // stdin
start.i32_const(runtime_page) // *iovs
start.i32_const(1) // iovs_len
start.i32_const(runtime_page + 1024) // *nwritten
start.call_import('wasi_unstable', 'fd_read')
start.drop() // ignore errno
}
`[` {
block_lbl := start.c_block([], [])
loop_lbl := start.c_loop([], [])
{
start.local_get(sp)
start.load8(.i32_t, false, 0, 0)
start.eqz(.i32_t)
start.c_br_if(block_lbl)
}
loop_labels << loop_lbl
block_labels << block_lbl
}
`]` {
loop_lbl := loop_labels.pop()
start.c_br(loop_lbl) // jump back to top
start.c_end(loop_lbl)
start.c_end(block_labels.pop())
}
else {}
}
}
}
@[noreturn]
fn usage() {
eprintln('Usage: bf <expr> <outfile>')
exit(1)
}
fn main() {
bf_expr := os.args[1] or { usage() }
outfile := os.args[2] or { usage() }
mut m := wasm.Module{}
m.enable_debug('wasm bf')
m.new_function_import('wasi_unstable', 'fd_write', [.i32_t, .i32_t, .i32_t, .i32_t],
[.i32_t])
m.new_function_import('wasi_unstable', 'fd_read', [.i32_t, .i32_t, .i32_t, .i32_t],
[.i32_t])
m.assign_memory('memory', true, 2, none)
mut start := m.new_function('_start', [], [])
{
generate_code(mut start, bf_expr)
}
m.commit(start, true)
bytes := m.compile()
os.write_file_array(outfile, bytes)!
}