Selaa lähdekoodia

ir back up, working on rewrite

Tobias Waldekranz.com 8 vuotta sitten
vanhempi
commit
a5e5286b12
7 muutettua tiedostoa jossa 195 lisäystä ja 426 poistoa
  1. 5 1
      func.h
  2. 18 20
      ir.c
  3. 27 26
      ir.h
  4. 74 70
      kprobe.c
  5. 63 303
      ply.c
  6. 4 3
      ply.h
  7. 4 3
      sym.h

+ 5 - 1
func.h

@@ -12,7 +12,11 @@ struct func {
12 12
 	int static_ret:1; 	/* return type is statically known */
13 13
 
14 14
 	int (*static_validate)(const struct func *, struct node *);
15
-	int (*type_infer)(const struct func *, struct node *);
15
+	int (*type_infer)     (const struct func *, struct node *);
16
+	int (*rewrite)        (const struct func *, struct node *, struct prog *);
17
+
18
+	int (*ir_pre) (const struct func *, struct node *, struct prog *);
19
+	int (*ir_post)(const struct func *, struct node *, struct prog *);
16 20
 };
17 21
 
18 22
 int func_static_validate(const struct func *func, struct node *n);

+ 18 - 20
ir.c

@@ -1,4 +1,3 @@
1
-#if 0
2 1
 #include <assert.h>
3 2
 #include <inttypes.h>
4 3
 #include <stdio.h>
@@ -208,7 +207,7 @@ void insn_dump(struct bpf_insn insn, FILE *fp)
208 207
 	__insn_dump(insn, insn.dst_reg, insn.src_reg, fp);
209 208
 }
210 209
 
211
-void vinsn_dump(vinsn_t *vi, FILE *fp)
210
+void vinsn_dump(struct vinsn *vi, FILE *fp)
212 211
 {
213 212
 	switch (vi->vitype) {
214 213
 	case VI_INSN:
@@ -230,12 +229,12 @@ void vinsn_dump(vinsn_t *vi, FILE *fp)
230 229
 	}
231 230
 }
232 231
 
233
-void ir_dump(ir_t *ir, FILE *fp)
232
+void ir_dump(struct ir *ir, FILE *fp)
234 233
 {
235 234
 	size_t i;
236 235
 
237 236
 	for (i = 0; i < ir->len; i++) {
238
-		vinsn_t *vi = &ir->vi[i];
237
+		struct vinsn *vi = &ir->vi[i];
239 238
 
240 239
 		switch (vi->vitype) {
241 240
 		case VI_INSN:
@@ -276,7 +275,7 @@ void ir_dump(ir_t *ir, FILE *fp)
276 275
 	}
277 276
 }
278 277
 
279
-static void ir_emit(ir_t *ir, vinsn_t *vi)
278
+static void ir_emit(struct ir *ir, struct vinsn *vi)
280 279
 {
281 280
 	ir->vi = realloc(ir->vi, (++ir->len)*sizeof(*vi));
282 281
 	assert(ir->vi);
@@ -284,9 +283,9 @@ static void ir_emit(ir_t *ir, vinsn_t *vi)
284 283
 	ir->vi[ir->len - 1] = *vi;
285 284
 }
286 285
 
287
-void ir_emit_insn(ir_t *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src)
286
+void ir_emit_insn(struct ir *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src)
288 287
 {
289
-	vinsn_t vi;
288
+	struct vinsn vi;
290 289
 
291 290
 	vi.vitype = VI_INSN;
292 291
 	vi.insn.bpf = bpf;
@@ -295,9 +294,9 @@ void ir_emit_insn(ir_t *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src)
295 294
 	ir_emit(ir, &vi);
296 295
 }
297 296
 
298
-void ir_emit_ldmap(ir_t *ir, uint16_t dst, sym_t *map)
297
+void ir_emit_ldmap(struct ir *ir, uint16_t dst, struct sym *map)
299 298
 {
300
-	vinsn_t vi;
299
+	struct vinsn vi;
301 300
 
302 301
 	vi.vitype = VI_LDMAP;
303 302
 	vi.map.reg = dst;
@@ -305,46 +304,46 @@ void ir_emit_ldmap(ir_t *ir, uint16_t dst, sym_t *map)
305 304
 	ir_emit(ir, &vi);
306 305
 }
307 306
 
308
-void ir_emit_label  (ir_t *ir, int16_t label)
307
+void ir_emit_label  (struct ir *ir, int16_t label)
309 308
 {
310
-	vinsn_t vi;
309
+	struct vinsn vi;
311 310
 
312 311
 	vi.vitype = VI_LABEL;
313 312
 	vi.label = label;
314 313
 	ir_emit(ir, &vi);
315 314
 }
316 315
 
317
-void ir_emit_reg_get(ir_t *ir, uint16_t reg)
316
+void ir_emit_reg_get(struct ir *ir, uint16_t reg)
318 317
 {
319
-	vinsn_t vi;
318
+	struct vinsn vi;
320 319
 
321 320
 	vi.vitype = VI_REG_GET;
322 321
 	vi.reg = reg;
323 322
 	ir_emit(ir, &vi);
324 323
 }
325 324
 
326
-void ir_emit_reg_put(ir_t *ir, uint16_t reg)
325
+void ir_emit_reg_put(struct ir *ir, uint16_t reg)
327 326
 {
328
-	vinsn_t vi;
327
+	struct vinsn vi;
329 328
 
330 329
 	vi.vitype = VI_REG_PUT;
331 330
 	vi.reg = reg;
332 331
 	ir_emit(ir, &vi);
333 332
 }
334 333
 
335
-int16_t ir_alloc_label (ir_t *ir)
334
+int16_t ir_alloc_label (struct ir *ir)
336 335
 {
337 336
 	return ir->next_label--;
338 337
 }
339 338
 
340
-uint16_t ir_alloc_register(ir_t *ir)
339
+uint16_t ir_alloc_register(struct ir *ir)
341 340
 {
342 341
 	return ir->next_reg++;
343 342
 }
344 343
 
345
-ir_t *ir_new(void)
344
+struct ir *ir_new(void)
346 345
 {
347
-	ir_t *ir;
346
+	struct ir *ir;
348 347
 
349 348
 	ir = calloc(1, sizeof(*ir));
350 349
 	assert(ir);
@@ -353,4 +352,3 @@ ir_t *ir_new(void)
353 352
 	ir->next_label = -1;
354 353
 	return ir;
355 354
 }
356
-#endif

+ 27 - 26
ir.h

@@ -2,6 +2,7 @@
2 2
 #define _PLY_IR_H
3 3
 
4 4
 #include <stdint.h>
5
+#include <stdio.h>
5 6
 #include <stdlib.h>
6 7
 
7 8
 #include <linux/bpf.h>
@@ -37,18 +38,18 @@
37 38
 #define LDXW(_dst, _off, _src)  INSN(BPF_LDX | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, _src, _off, 0)
38 39
 #define LDXDW(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_DW) | BPF_MEM, _dst, _src, _off, 0)
39 40
 
40
-typedef struct sym sym_t;
41
+struct sym;
41 42
 
42
-typedef enum vitype {
43
+enum vitype {
43 44
 	VI_INSN,
44 45
 	VI_LDMAP,
45 46
 	VI_LABEL,
46 47
 	VI_REG_GET,
47 48
 	VI_REG_PUT,
48
-} vitype_t;
49
+};
49 50
 
50
-typedef struct vinsn {
51
-	vitype_t vitype;
51
+struct vinsn {
52
+	enum vitype vitype;
52 53
 
53 54
 	union {
54 55
 		struct {
@@ -62,33 +63,33 @@ typedef struct vinsn {
62 63
 
63 64
 		struct {
64 65
 			uint16_t reg;
65
-			sym_t *sym;
66
+			struct sym *sym;
66 67
 		} map;
67 68
 	};
68
-} vinsn_t;
69
+};
69 70
 
70
-typedef struct ir {
71
-	vinsn_t *vi;
71
+struct ir {
72
+	struct vinsn *vi;
72 73
 	size_t len;
73 74
 
74 75
 	int16_t next_label;
75 76
 	uint16_t next_reg;
76
-} ir_t;
77
+};
77 78
 
78 79
 void insn_dump(struct bpf_insn insn, FILE *fp);
79
-void vinsn_dump(vinsn_t *vi, FILE *fp);
80
-void ir_dump(ir_t *ir, FILE *fp);
80
+void vinsn_dump(struct vinsn *vi, FILE *fp);
81
+void ir_dump(struct ir *ir, FILE *fp);
81 82
 
82
-int16_t  ir_alloc_label   (ir_t *ir);
83
-uint16_t ir_alloc_register(ir_t *ir);
83
+int16_t  ir_alloc_label   (struct ir *ir);
84
+uint16_t ir_alloc_register(struct ir *ir);
84 85
 
85
-void ir_emit_insn   (ir_t *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
86
-void ir_emit_ldmap  (ir_t *ir, uint16_t dst, sym_t *map);
87
-void ir_emit_label  (ir_t *ir, int16_t label);
88
-void ir_emit_reg_get(ir_t *ir, uint16_t reg);
89
-void ir_emit_reg_put(ir_t *ir, uint16_t reg);
86
+void ir_emit_insn   (struct ir *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
87
+void ir_emit_ldmap  (struct ir *ir, uint16_t dst, struct sym *map);
88
+void ir_emit_label  (struct ir *ir, int16_t label);
89
+void ir_emit_reg_get(struct ir *ir, uint16_t reg);
90
+void ir_emit_reg_put(struct ir *ir, uint16_t reg);
90 91
 
91
-static inline void ir_emit_call(ir_t *ir, enum bpf_func_id func)
92
+static inline void ir_emit_call(struct ir *ir, enum bpf_func_id func)
92 93
 {
93 94
 	ir_emit_reg_get(ir, BPF_REG_0);
94 95
 	ir_emit_reg_get(ir, BPF_REG_1);
@@ -105,22 +106,22 @@ static inline void ir_emit_call(ir_t *ir, enum bpf_func_id func)
105 106
 	ir_emit_reg_put(ir, BPF_REG_0);
106 107
 }
107 108
 
108
-ir_t *ir_new(void);
109
+struct ir *ir_new(void);
109 110
 
110
-typedef enum irloc {
111
+enum irloc {
111 112
 	LOC_IMM   = (1 << 0),
112 113
 	LOC_REG   = (1 << 1),
113 114
 	LOC_STACK = (1 << 2),
114
-} irloc_t;
115
+};
115 116
 
116
-typedef struct irstate {
117
+struct irstate {
117 118
 	int loc;
118 119
 
119 120
 	uint16_t reg;
120 121
 	int16_t stack;
121
-} irstate_t;
122
+};
122 123
 
123
-static inline void irs_alloc_reg(irstate_t *irs, ir_t *ir)
124
+static inline void irs_alloc_reg(struct irstate *irs, struct ir *ir)
124 125
 {
125 126
 	irs->loc = LOC_REG;
126 127
 	irs->reg = ir_alloc_register(ir);

+ 74 - 70
kprobe.c

@@ -5,28 +5,37 @@
5 5
 
6 6
 #include <linux/ptrace.h>
7 7
 
8
+#include "arch.h"
8 9
 #include "func.h"
10
+#include "ir.h"
9 11
 #include "node.h"
10 12
 #include "ply.h"
11 13
 #include "sym.h"
12 14
 #include "type.h"
13 15
 
14 16
 struct kprobe {
17
+	int use_ctx:1;
18
+
19
+	struct irstate ctx_irs;
15 20
 };
16 21
 
17
-/* static int kprobe_ir_prologue(prog_t *prog) */
18
-/* { */
19
-/* 	sym_t *ctx = sym_get(prog->locals, "ctx"); */
22
+/* ctx */
23
+
24
+static struct type t_pt_regsp = {
25
+	.ttype = T_POINTER,
26
+
27
+	.ptr.type = &t_pt_regs,
28
+};
20 29
 
21
-/* 	if (!ctx) */
22
-/* 		return 0; */
30
+static const struct func kprobe_ctx_func = {
31
+	.name = "ctx",
32
+
33
+	.type = &t_pt_regsp,
34
+	.static_ret = 1,
35
+};
23 36
 
24
-/* 	irs_alloc_reg(&ctx->irs, prog->ir); */
25 37
 
26
-/* 	/\* kernel sets r1 to the address of the context *\/ */
27
-/* 	ir_emit_insn(prog->ir, MOV(0, 0), ctx->irs.reg, BPF_REG_1); */
28
-/* 	return 0; */
29
-/* } */
38
+/* argN */
30 39
 
31 40
 static inline int is_arg(const char *name)
32 41
 {
@@ -35,63 +44,35 @@ static inline int is_arg(const char *name)
35 44
 		&& (name[3] >= '0' && name[3] <= '9');
36 45
 }
37 46
 
38
-/* static int kprobe_rewrite_arg(prog_t *prog, node_t *n) */
39
-/* { */
40
-/* 	const char *reg; */
41
-/* 	int arg = n->ident[3] - '0'; */
42
-/* 	node_t *new, *ctx; */
43
-
44
-/* 	reg = arch_register_argument(arg); */
45
-/* 	if (!reg) { */
46
-/* 		node_print(n, stderr); */
47
-/* 		fputs(": the location of this argument is unknown\n", stderr); */
48
-/* 		/\* TODO: add ABI mappings for specifying arguments */
49
-/* 		 * passed on the stack. *\/ */
50
-/* 		return -EINVAL; */
51
-/* 	} */
52
-
53
-/* 	ctx = node_ident("ctx"); */
54
-
55
-/* 	/\* argN => (*ctx).REG *\/ */
56
-/* 	new = node_vlist(node_keyword('.', 0), */
57
-/* 			 node_vlist(node_keyword('*', 0), */
58
-/* 				    ctx, */
59
-/* 				    NULL), */
60
-/* 			 node_string(reg), */
61
-/* 			 NULL); */
62
-
63
-/* 	ctx->type = type_ptr_of(&t_pt_regs); */
64
-/* 	new->type = n->type; */
65
-/* 	new->list->type = &t_void; */
66
-/* 	new->list->next->type = &t_pt_regs; */
67
-/* 	new->list->next->list->type = &t_void; */
68
-/* 	node_replace(n, new); */
69
-
70
-/* 	return sym_add(prog->locals, ctx->ident, ctx->type, &ctx->sym); */
71
-/* } */
72
-
73
-/* static int kprobe_rewrite_node(prog_t *prog, node_t *n) */
74
-/* { */
75
-/* 	if ((n->ntype == N_IDENT) && is_arg(n->ident)) */
76
-/* 		return kprobe_rewrite_arg(prog, n); */
77
-
78
-/* 	return 0; */
79
-/* } */
80
-
81
-/* static int kprobe_resolve(prog_t *prog, node_t *n) */
82
-/* { */
83
-/* 	type_t *t; */
84
-
85
-/* 	if (is_arg(n->ident)) */
86
-/* 		t = &t_ulong; */
87
-/* 	else if (!strcmp(n->ident, "ctx")) */
88
-/* 		t = type_ptr_of(&t_pt_regs); */
89
-/* 	else */
90
-/* 		return -ENOENT; */
91
-
92
-/* 	n->type = t; */
93
-/* 	return sym_add(prog->locals, n->ident, t, &n->sym); */
94
-/* } */
47
+static int kprobe_arg_rewrite(const struct func *func, struct node *n,
48
+			      struct prog *prog)
49
+{
50
+	struct node *new;
51
+	const char *reg;
52
+	int arg;
53
+
54
+	arg = n->ident.name[3] - '0';
55
+	reg = arch_register_argument(arg);
56
+	if (!reg) {
57
+		_e("%#N: the location of %N is unknown\n", n, n);
58
+
59
+		/* TODO: add ABI mappings for specifying arguments
60
+		 * passed on the stack. */
61
+		return -EINVAL;
62
+	}
63
+
64
+	/* argN => (*ctx).REG */
65
+	new = node_expr(".",
66
+			node_expr("*", node_ident("ctx"), NULL),
67
+			node_string((char *)reg),
68
+			NULL);
69
+
70
+	ast_fprint(stdout, n);
71
+	ast_fprint(stdout, new);
72
+
73
+	node_replace(n, new);
74
+	return 0;
75
+}
95 76
 
96 77
 static const struct func kprobe_arg_func = {
97 78
 	.name = "argN",
@@ -100,10 +81,30 @@ static const struct func kprobe_arg_func = {
100 81
 	 * figure out the real type. */
101 82
 	.type = &t_ulong,
102 83
 	.static_ret = 1,
84
+
85
+	.rewrite = kprobe_arg_rewrite,
103 86
 };
104 87
 
88
+
89
+/*  */
90
+
91
+static int kprobe_ir_pre(struct prog *prog)
92
+{
93
+	struct kprobe *kp = prog->provider_data;
94
+
95
+	if (!kp->use_ctx)
96
+		return 0;
97
+
98
+	irs_alloc_reg(&kp->ctx_irs, prog->ir);
99
+
100
+	/* kernel sets r1 to the address of the context */
101
+	ir_emit_insn(prog->ir, MOV(0, 0), kp->ctx_irs.reg, BPF_REG_1);
102
+	return 0;
103
+}
104
+
105 105
 static int kprobe_sym_alloc(struct prog *prog, struct node *n)
106 106
 {
107
+	struct kprobe *kp = prog->provider_data;
107 108
 	const struct func *func = NULL;
108 109
 	int err;
109 110
 
@@ -111,8 +112,11 @@ static int kprobe_sym_alloc(struct prog *prog, struct node *n)
111 112
 	case N_EXPR:
112 113
 		break;
113 114
 	case N_IDENT:
114
-		if (is_arg(n->ident.name))
115
-			func = &kprobe_arg_func;
115
+		if (!is_arg(n->ident.name))
116
+			break;
117
+
118
+		func = &kprobe_arg_func;
119
+		kp->use_ctx = 1;
116 120
 		break;
117 121
 	default:
118 122
 		break;
@@ -146,7 +150,7 @@ static int kprobe_probe(struct prog *prog)
146 150
 struct provider kprobe = {
147 151
 	.name = "kprobe",
148 152
 
149
-	/* .ir_prologue = kprobe_ir_prologue, */
153
+	.ir_pre = kprobe_ir_pre,
150 154
 	/* .rewrite_node = kprobe_rewrite_node, */
151 155
 	/* .resolve = kprobe_resolve, */
152 156
 	.sym_alloc = kprobe_sym_alloc,

+ 63 - 303
ply.c

@@ -5,6 +5,7 @@
5 5
 #include <string.h>
6 6
 
7 7
 #include "func.h"
8
+#include "ir.h"
8 9
 #include "node.h"
9 10
 #include "ply.h"
10 11
 #include "sym.h"
@@ -100,7 +101,7 @@ struct ctx *ctx_get(void)
100 101
 
101 102
 	prog->provider = provider_get("k");
102 103
 	prog->provider->probe(prog);
103
-	/* prog->ir = ir_new(); */
104
+	prog->ir = ir_new();
104 105
 	ctx->progs[0] = prog;
105 106
 
106 107
 	/* PROBE1 */
@@ -132,7 +133,7 @@ struct ctx *ctx_get(void)
132 133
 
133 134
 	prog->provider = provider_get("k");
134 135
 	prog->provider->probe(prog);
135
-	/* prog->ir = ir_new(); */
136
+	prog->ir = ir_new();
136 137
 	ctx->progs[1] = prog;
137 138
 
138 139
 	return ctx;
@@ -167,321 +168,76 @@ int pass_sym_alloc(struct node *n, void *_prog)
167 168
 	return err;
168 169
 }
169 170
 
170
-/* int infer_type_list(struct prog *prog, struct node *n) */
171
-/* { */
172
-/* 	type_t *t; */
173 171
 
174
-/* 	/\* list of lists (code block) => void *\/ */
175
-/* 	if (n->list->ntype == N_LIST) { */
176
-/* 		n->type = &t_void; */
177
-/* 		return 0; */
178
-/* 	} */
179
-
180
-/* 	t = n->list->type; */
181
-/* 	if (!t) */
182
-/* 		return 0; */
183
-
184
-/* 	switch (t->ttype) { */
185
-/* 	case T_FUNC: */
186
-/* 		n->type = t->t.func.type; */
187
-/* 		break; */
188
-/* 	default: */
189
-/* 		n->type = t; */
190
-/* 	} */
191
-/* 	return 0; */
192
-/* } */
193
-
194
-/* int infer_type_keyword(struct prog *prog, struct node *n) */
195
-/* { */
196
-/* 	struct node *dst, *src; */
197
-
198
-/* 	switch (n->keyword.class) { */
199
-/* 	case KW_ASSIGN: */
200
-/* 		dst = node_next(n); */
201
-/* 		src = node_next(dst); */
202
-/* 		assert(dst && src); */
203
-
204
-/* 		if (!src->type) */
205
-/* 			return 0; */
206
-
207
-/* 		/\* TODO: assignment is statement for now. do we need */
208
-/* 		 * c-style assignment expressions? e.g `a = b = 2;` *\/ */
209
-/* 		n->type = &t_void; */
210
-
211
-/* 		if (dst->type) */
212
-/* 			return 0; */
172
+int pass_type_infer(struct node *n, void *_prog)
173
+{
174
+	struct prog *prog = _prog;
213 175
 
214
-/* 		dst->type = src->type; */
176
+	if (n->sym->func->type_infer)
177
+		return n->sym->func->type_infer(n->sym->func, n);
215 178
 
216
-/* 		if (dst->ntype != N_IDENT) */
217
-/* 			return 0; */
179
+	/* TODO recurse as long as we're infering new types */
180
+	return 0;
181
+}
218 182
 
219
-/* 		return sym_add(dst->sym->st, dst->ident, dst->type, NULL); */
183
+int pass_rewrite(struct node *n, void *_prog)
184
+{
185
+	struct prog *prog = _prog;
220 186
 
221
-/* 	case KW_BINOP: */
222
-/* 		dst = node_next(n); */
223
-/* 		src = node_next(dst); */
224
-/* 		assert(dst && src); */
187
+	if (n->sym->func->rewrite)
188
+		return n->sym->func->rewrite(n->sym->func, n, prog);
225 189
 
226
-/* 		if (!(src->type && dst->type && type_equal(src->type, dst->type))) */
227
-/* 			return 0; */
190
+	return 0;
191
+}
228 192
 
229
-/* 		n->type = dst->type; */
230
-/* 		return 0; */
193
+int pass_ir_pre(struct node *n, void *_prog)
194
+{
195
+	struct prog *prog = _prog;
231 196
 
232
-/* 	default: */
233
-/* 		n->type = &t_void; */
234
-/* 		return 0; */
235
-/* 	} */
197
+	if (n->sym->func->ir_pre)
198
+		return n->sym->func->ir_pre(n->sym->func, n, prog);
236 199
 
237
-/* 	return -ENOSYS; */
238
-/* } */
200
+	return 0;
201
+}
239 202
 
240
-/* int infer_type_sym(struct prog *prog, struct node *n) */
241
-/* { */
242
-/* 	struct node *parent, *key; */
203
+int pass_ir_post(struct node *n, void *_prog)
204
+{
205
+	struct prog *prog = _prog;
243 206
 
244
-/* 	if (n->sym->type) { */
245
-/* 		/\* the symbol type could have been inferred in another */
246
-/* 		 * probe, in that case copy the type to this node. *\/ */
247
-/* 		if (!n->type) */
248
-/* 			n->type = n->sym->type; */
207
+	if (n->sym->func->ir_post)
208
+		return n->sym->func->ir_post(n->sym->func, n, prog);
249 209
 
250
-/* 		return 0; */
251
-/* 	} */
210
+	return 0;
211
+}
252 212
 
253
-/* 	parent = node_up(n); */
254
-/* 	key = node_next(n); */
213
+int run_ir(struct pass *pass, struct ctx *ctx)
214
+{
215
+	struct prog **progp;
216
+	int err;
255 217
 
256
-/* 	/\* match `somemap[somekey]` where the type of the entire */
257
-/* 	 * expression and the type of the key is known, since that */
258
-/* 	 * means the type of the map itself is also known. *\/ */
259
-/* 	if (parent && parent->type */
260
-/* 	    && (parent->list->ntype == N_KEYWORD) */
261
-/* 	    && (parent->list->keyword.class == KW_SUBSCRIPT) */
262
-/* 	    && key && key->type) { */
263
-/* 		n->type = type_map_of(key->type, parent->type); */
218
+	for (progp = ctx->progs; *progp; progp++) {
219
+		struct prog *prog = *progp;
264 220
 
265
-/* 		return sym_add(n->sym->st, n->ident, n->type, NULL); */
266
-/* 	} */
221
+		err = prog->provider->ir_pre ?
222
+			prog->provider->ir_pre(prog) : 0;
223
+		if (err)
224
+			return err;
267 225
 
268
-/* 	return 0; */
269
-/* } */
226
+		err = node_walk(prog->ast, pass_ir_pre, pass_ir_post, prog);
227
+		if (err)
228
+			return err;
270 229
 
271
-int pass_type_infer(struct node *n, void *_prog)
272
-{
273
-	struct prog *prog = _prog;
230
+		err = prog->provider->ir_post ?
231
+			prog->provider->ir_post(prog) : 0;
232
+		if (err)
233
+			return err;
274 234
 
275
-	if (n->sym->func->type_infer)
276
-		return n->sym->func->type_infer(n->sym->func, n);
235
+		ir_emit_insn(prog->ir, EXIT, 0, 0);
236
+	}
277 237
 
278 238
 	return 0;
279 239
 }
280 240
 
281
-/* int validate_func(struct node *n) */
282
-/* { */
283
-/* 	struct node *arg; */
284
-/* 	field_t *f; */
285
-/* 	int i; */
286
-
287
-/* 	for (arg = node_next(n), f = n->type->t.func.args, i = 1; */
288
-/* 	     arg && f && f->type; arg = node_next(arg), f++, i++) { */
289
-/* 		if (type_compatible(arg->type, f->type)) */
290
-/* 			continue; */
291
-
292
-/* 		node_print(n, stderr); */
293
-/* 		fprintf(stderr, ": incompatible type of argument %d (", i); */
294
-/* 		type_dump(arg->type, stderr); */
295
-/* 		fputs("), expected ", stderr); */
296
-/* 		type_dump(f->type, stderr); */
297
-/* 		fputs("\n", stderr); */
298
-/* 		return -EINVAL; */
299
-/* 	} */
300
-
301
-/* 	if (!arg && (!f || !f->type)) */
302
-/* 		return 0; */
303
-
304
-/* 	if (arg) { */
305
-/* 		node_print(n, stderr); */
306
-/* 		fprintf(stderr, ": too many arguments, expected %d", i); */
307
-/* 		return -EINVAL; */
308
-/* 	} */
309
-
310
-/* 	if (f->optional) */
311
-/* 		return 0; */
312
-
313
-/* 	node_print(n, stderr); */
314
-/* 	fputs(": too few arguments", stderr); */
315
-/* 	return -EINVAL;	 */
316
-/* } */
317
-
318
-/* int pass_validate_types(struct node *n, void *_prog) */
319
-/* { */
320
-/* 	struct prog *prog = _prog; */
321
-
322
-/* 	node_print(n, stdout); putchar('\n');  */
323
-/* 	if (!n->type) { */
324
-/* 		node_print(n, stderr); */
325
-/* 		fputs(": type unknown\n", stderr); */
326
-/* 		return -EINVAL; */
327
-/* 	} */
328
-
329
-/* 	if (n->ntype != N_LIST) */
330
-/* 		return 0; */
331
-
332
-/* 	if (n->list->ntype != N_IDENT) */
333
-/* 		return 0; */
334
-
335
-/* 	assert(n->list->type->ttype == T_FUNC); */
336
-/* 	return validate_func(n->list); */
337
-/* } */
338
-
339
-/* int validate_syms(struct prog *prog) */
340
-/* { */
341
-/* 	return 0; */
342
-/* } */
343
-
344
-/* int run_validate_types(struct pass *pass, struct ctx *ctx) */
345
-/* { */
346
-/* 	struct prog **prog; */
347
-/* 	int err; */
348
-
349
-/* 	for (prog = ctx->progs; *prog; prog++) { */
350
-/* 		/\* check syms first to give better error messages. */
351
-/* 		 * e.g. "i: type unknown", not "b-: type unknown" *\/ */
352
-/* 		err = validate_syms(*prog); */
353
-/* 		if (err) */
354
-/* 			return err; */
355
-
356
-/* 		err = node_walk((*prog)->ast, pass->pre, pass->post, *prog); */
357
-/* 		if (err) */
358
-/* 			return err; */
359
-/* 	} */
360
-
361
-/* 	return 0; */
362
-
363
-/* } */
364
-
365
-/* int rewrite_const_math(struct node *n) */
366
-/* { */
367
-/* 	int64_t result; */
368
-/* 	struct node *a, *b, *new; */
369
-/* 	int op; */
370
-
371
-/* 	/\* TODO: handle L/UL/ULL correctly *\/ */
372
-	
373
-/* 	op = n->list->keyword.op; */
374
-/* 	a = node_next(n->list); */
375
-/* 	b = node_next(a); */
376
-
377
-/* 	switch (op) { */
378
-/* 	case '*': result = a->num *  b->num; break; */
379
-/* 	case '/': result = a->num /  b->num; break; */
380
-/* 	case '%': result = a->num %  b->num; break; */
381
-/* 	case '+': result = a->num +  b->num; break; */
382
-/* 	case '-': result = a->num -  b->num; break; */
383
-/* 	case '<': result = a->num << b->num; break; */
384
-/* 	case '>': result = a->num >> b->num; break; */
385
-/* 	default: return 0; */
386
-/* 	} */
387
-
388
-/* 	new = node_num(result); */
389
-/* 	new->type = n->type; */
390
-/* 	return node_replace(n, new); */
391
-/* } */
392
-
393
-/* int pass_rewrite_ast(struct node *n, void *_prog) */
394
-/* { */
395
-/* 	struct prog *prog = _prog; */
396
-/* 	provider_t *global = provider_get(":"); */
397
-/* 	int err; */
398
-
399
-/* 	if (prog->provider->rewrite_node) { */
400
-/* 		err = prog->provider->rewrite_node(prog, n); */
401
-/* 		if (err) */
402
-/* 			return err; */
403
-/* 	} */
404
-
405
-/* 	if (global->rewrite_node) { */
406
-/* 		err = global->rewrite_node(prog, n); */
407
-/* 		if (err) */
408
-/* 			return err; */
409
-/* 	} */
410
-
411
-/* 	/\* pre-compute binops where both sides are constants *\/ */
412
-/* 	if ((n->ntype == N_LIST) */
413
-/* 	    && (n->list->ntype == N_KEYWORD) */
414
-/* 	    && (n->list->keyword.class == KW_BINOP) */
415
-/* 	    && (node_next(n->list)->ntype == N_NUM) */
416
-/* 	    && (node_next(node_next(n->list))->ntype == N_NUM)) */
417
-/* 		return rewrite_const_math(n); */
418
-
419
-/* 	return 0; */
420
-/* } */
421
-
422
-/* int generate_ir_ident(struct prog *prog, struct node *n) */
423
-/* { */
424
-
425
-/* 	switch (n->sym->type->ttype) { */
426
-/* 	case T_FUNC: */
427
-/* 		return n->sym->type->t.func.generate_ir(prog, n); */
428
-/* 	case T_MAP: */
429
-/* 		ir_emit_ldmap(prog->ir, BPF_REG_0, n->sym); */
430
-/* 		return 0; */
431
-/* 	default: */
432
-/* 		break; */
433
-/* 	} */
434
-
435
-/* 	return 0; */
436
-/* } */
437
-
438
-/* int pass_generate_ir(struct node *n, void *_prog) */
439
-/* { */
440
-/* 	struct prog *prog = _prog; */
441
-
442
-/* 	switch (n->ntype) { */
443
-/* 	case N_LIST: */
444
-/* 		return 0; */
445
-/* 	case N_IDENT: */
446
-/* 		return generate_ir_ident(prog, n); */
447
-
448
-/* 	default: */
449
-/* 		break; */
450
-/* 	} */
451
-/* 	return 0; */
452
-/* } */
453
-
454
-/* int run_generate_ir(struct pass *pass, struct ctx *ctx) */
455
-/* { */
456
-/* 	struct prog **progp; */
457
-/* 	int err; */
458
-
459
-/* 	for (progp = ctx->progs; *progp; progp++) { */
460
-/* 		struct prog *prog = *progp; */
461
-
462
-/* 		int return_label = ir_alloc_label(prog->ir); */
463
-
464
-/* 		err = prog->provider->ir_prologue ? */
465
-/* 			prog->provider->ir_prologue(prog) : 0; */
466
-/* 		if (err) */
467
-/* 			return err; */
468
-
469
-/* 		err = node_walk(prog->ast, NULL, pass_generate_ir, prog); */
470
-/* 		if (err) */
471
-/* 			return err; */
472
-
473
-/* 		err = prog->provider->ir_epilogue ? */
474
-/* 			prog->provider->ir_epilogue(prog) : 0; */
475
-/* 		if (err) */
476
-/* 			return err; */
477
-
478
-/* 		ir_emit_label(prog->ir, return_label); */
479
-/* 		ir_emit_insn(prog->ir, EXIT, 0, 0); */
480
-/* 	} */
481
-
482
-/* 	return 0; */
483
-/* } */
484
-
485 241
 int run_walk(struct pass *pass, struct ctx *ctx)
486 242
 {
487 243
 	struct prog **prog;
@@ -498,13 +254,17 @@ int run_walk(struct pass *pass, struct ctx *ctx)
498 254
 
499 255
 struct pass passes[] = {
500 256
 	{ .run = run_walk, .post = pass_sym_alloc },
257
+	/* node->sym ok */
501 258
 	{ .run = run_walk, .post = pass_type_infer },
502
-	/* { .run = run_walk, .post = pass_infer_types }, */
503
-	/* { .run = run_walk, .post = pass_infer_types }, */
504
-	/* { .run = run_validate_types, .post = pass_validate_types }, */
505
-	/* { .run = run_walk, .post = pass_rewrite_ast }, */
506
-	/* { .run = run_generate_ir }, */
507
-
259
+	/* node->sym->type ok */
260
+	/* user input is accepted. we'll now start rewriting the ast,
261
+	 * so errors beyond this point are internal errors. */
262
+	{ .run = run_walk, .post = pass_rewrite },
263
+	{ .run = run_ir },
264
+	/* program flattened to vBPF instructions, now rewrite it to
265
+	 * fit into the actual hw/vm. */
266
+
267
+	/* BPF program ready */
508 268
 	{ NULL }
509 269
 };
510 270
 
@@ -526,8 +286,8 @@ int main(void)
526 286
 		ast_fprint(stdout, (*prog)->ast);
527 287
 		printf("\n-- locals\n");
528 288
 		symtab_dump((*prog)->locals, stdout);
529
-		/* printf("-- ir\n"); */
530
-		/* ir_dump((*prog)->ir, stdout); */
289
+		printf("-- ir\n");
290
+		ir_dump((*prog)->ir, stdout);
531 291
 	}
532 292
 
533 293
 	printf("\n\n-- globals\n");

+ 4 - 3
ply.h

@@ -5,6 +5,7 @@
5 5
 
6 6
 struct node;
7 7
 struct symtab;
8
+struct ir;
8 9
 
9 10
 struct prog {
10 11
 	const char *probe;
@@ -19,7 +20,7 @@ struct prog {
19 20
 	struct provider *provider;
20 21
 	void *provider_data;
21 22
 
22
-	/* ir_t *ir; */
23
+	struct ir *ir;
23 24
 };
24 25
 
25 26
 struct ctx {
@@ -38,8 +39,8 @@ struct provider {
38 39
 	int (*sym_alloc)(struct prog *, struct node *);
39 40
 	/* int (*resolve)(struct prog *, struct node *); */
40 41
 	/* int (*rewrite_node)(struct prog *, struct node *); */
41
-	/* int (*ir_prologue)(struct prog *); */
42
-	/* int (*ir_epilogue)(struct prog *); */
42
+	int (*ir_pre)(struct prog *);
43
+	int (*ir_post)(struct prog *);
43 44
 };
44 45
 
45 46
 void provider_register(struct provider *p);

+ 4 - 3
sym.h

@@ -3,10 +3,11 @@
3 3
 
4 4
 #include <stdint.h>
5 5
 
6
-struct symtab;
7
-
8
-struct type;
9 6
 struct func;
7
+struct node;
8
+struct type;
9
+
10
+struct symtab;
10 11
 
11 12
 struct sym {
12 13
 	struct symtab *st;