Tobias Waldekranz.com 8 lat temu
rodzic
commit
9cc575d452
6 zmienionych plików z 195 dodań i 69 usunięć
  1. 143 55
      global.c
  2. 10 0
      ir.c
  3. 2 0
      ir.h
  4. 34 11
      ply.c
  5. 4 2
      type.c
  6. 2 1
      type.h

+ 143 - 55
global.c

@@ -165,7 +165,22 @@ static int global_deref_type_infer(const struct func *func, struct node *n)
165 165
 
166 166
 /* :map */
167 167
 
168
-static int global_map_ir_pre_key(struct node *n, struct prog *prog)
168
+static int map_ir_update(struct node *n, struct prog *prog)
169
+{
170
+	struct node *map = n->expr.args;
171
+
172
+	ir_emit_ldmap(prog->ir, BPF_REG_1, map->sym);
173
+	ir_emit_insn(prog->ir, MOV, BPF_REG_2, BPF_REG_BP);
174
+	ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, map->sym->irs.stack), BPF_REG_2, 0);
175
+	ir_emit_insn(prog->ir, MOV, BPF_REG_3, BPF_REG_BP);
176
+	ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, n->sym->irs.stack), BPF_REG_3, 0);
177
+	ir_emit_insn(prog->ir, MOV_IMM(0), BPF_REG_4, 0);
178
+	ir_emit_insn(prog->ir, CALL(BPF_FUNC_map_update_elem), 0, 0);
179
+	/* TODO: if (r0) exit(r0); */
180
+	return 0;
181
+}
182
+
183
+static int map_ir_pre_key(struct node *n, struct prog *prog)
169 184
 {
170 185
 	struct node *map = n->expr.args, *arg;
171 186
 	struct type *ktype = type_base(map->sym->type->map.ktype);
@@ -198,8 +213,8 @@ static int global_map_ir_pre_key(struct node *n, struct prog *prog)
198 213
 	return 0;
199 214
 }
200 215
 
201
-static int global_map_ir_pre(const struct func *func, struct node *n,
202
-			     struct prog *prog)
216
+static int map_ir_pre(const struct func *func, struct node *n,
217
+		      struct prog *prog)
203 218
 {
204 219
 	struct irstate *kirs;
205 220
 	struct node *map = n->expr.args;
@@ -210,7 +225,7 @@ static int global_map_ir_pre(const struct func *func, struct node *n,
210 225
 
211 226
 
212 227
 	if (ktype->ttype == T_STRUCT)
213
-		return global_map_ir_pre_key(n, prog);
228
+		return map_ir_pre_key(n, prog);
214 229
 
215 230
 	kirs = &map->next->sym->irs;
216 231
 	if (!kirs->loc) {
@@ -220,8 +235,8 @@ static int global_map_ir_pre(const struct func *func, struct node *n,
220 235
 	return 0;
221 236
 }
222 237
 
223
-static int global_map_ir_post(const struct func *func, struct node *n,
224
-			      struct prog *prog)
238
+static int map_ir_post(const struct func *func, struct node *n,
239
+		       struct prog *prog)
225 240
 {
226 241
 	struct node *map = n->expr.args, *arg;
227 242
 	struct type *ktype = type_base(map->sym->type->map.ktype);
@@ -231,10 +246,16 @@ static int global_map_ir_post(const struct func *func, struct node *n,
231 246
 	int16_t lmiss, lhit;
232 247
 
233 248
 	arg = map->next;
234
-	tfields_foreach(f, ktype->sou.fields) {
235
-		offset = type_offsetof(ktype, f->name);
236
-		ir_emit_sym_to_stack(prog->ir, stack + offset, arg->sym);
237
-		arg = arg->next;
249
+
250
+	if (ktype->ttype == T_STRUCT) {
251
+		tfields_foreach(f, ktype->sou.fields) {
252
+			offset = type_offsetof(ktype, f->name);
253
+			ir_emit_sym_to_stack(prog->ir, stack + offset, arg->sym);
254
+			arg = arg->next;
255
+		}
256
+	} else {
257
+		ir_emit_sym_to_stack(prog->ir, stack, arg->sym);
258
+		assert(!arg->next);
238 259
 	}
239 260
 
240 261
 	n->sym->irs.hint.stack = 1;
@@ -264,7 +285,7 @@ static int global_map_ir_post(const struct func *func, struct node *n,
264 285
 	return 0;
265 286
 }
266 287
 
267
-static struct type *global_map_ktype(struct node *n)
288
+static struct type *map_key_type(struct node *n)
268 289
 {
269 290
 	struct node *map, *key;
270 291
 	struct type *ktype;
@@ -296,22 +317,44 @@ static struct type *global_map_ktype(struct node *n)
296 317
 	return ktype;
297 318
 }
298 319
 
299
-static int global_map_type_infer(const struct func *func, struct node *n)
320
+static int map_type_validate(struct node *n)
300 321
 {
301
-	struct node *map = n->expr.args;
322
+	/* TODO */
323
+	return 0;
324
+}
302 325
 
303
-	if (!map->sym->type)
326
+static int map_type_infer(const struct func *func, struct node *n)
327
+{
328
+	struct node *map, *key;
329
+	struct type *ktype;
330
+
331
+	map = n->expr.args;
332
+	if (!map->sym)
304 333
 		return 0;
305 334
 
306
-	/* TODO validate key against known type */
335
+	if (map->sym->type) {
336
+		if (!n->sym->type)
337
+			/* given `m[key]` where m's type is known,
338
+			 * infer that the expression's type is equal
339
+			 * to m's value type. */
340
+			n->sym->type = map->sym->type->map.vtype;
341
+
342
+		return map_type_validate(n);
343
+	}
307 344
 
308
-	/* given `m[key]` where m's type is known, infer that the
309
-	 * expression's type is equal to m's value type. */
310
-	n->sym->type = map->sym->type->map.vtype;
345
+	if (!n->sym->type)
346
+		return 0;
347
+
348
+	for (key = map->next; key; key = key->next) {
349
+		if (type_sizeof(key->sym->type) < 0)
350
+			return 0;
351
+	}
352
+
353
+	map->sym->type = type_map_of(map_key_type(n), n->sym->type);
311 354
 	return 0;
312 355
 }
313 356
 
314
-static int global_map_static_validate(const struct func *func, struct node *n)
357
+static int map_static_validate(const struct func *func, struct node *n)
315 358
 {
316 359
 	if (n->expr.args->ntype != N_IDENT) {
317 360
 		_e("%#N: can't lookup a key in %N, which is not a map.\n",
@@ -347,7 +390,7 @@ static int global_assign_ir_pre(const struct func *func, struct node *n,
347 390
 static int global_assign_ir_post(const struct func *func, struct node *n,
348 391
 				 struct prog *prog)
349 392
 {
350
-	struct node *lval, *rval, *map;
393
+	struct node *lval, *rval;
351 394
 
352 395
 	lval = n->expr.args;
353 396
 	rval = lval->next;
@@ -356,38 +399,13 @@ static int global_assign_ir_post(const struct func *func, struct node *n,
356 399
 	if (!node_is(lval, "{}"))
357 400
 		return 0;
358 401
 
359
-	map = lval->expr.args;
360
-
361
-	ir_emit_ldmap(prog->ir, BPF_REG_1, map->sym);
362
-	ir_emit_insn(prog->ir, MOV, BPF_REG_2, BPF_REG_BP);
363
-	ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, map->sym->irs.stack), BPF_REG_2, 0);
364
-	ir_emit_insn(prog->ir, MOV, BPF_REG_3, BPF_REG_BP);
365
-	ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, lval->sym->irs.stack), BPF_REG_3, 0);
366
-	ir_emit_insn(prog->ir, MOV_IMM(0), BPF_REG_4, 0);
367
-	ir_emit_insn(prog->ir, CALL(BPF_FUNC_map_update_elem), 0, 0);
368
-	/* TODO: if (r0) exit(r0); */
369
-	return 0;
370
-}
371
-
372
-static int global_assign_type_infer_map(struct node *n)
373
-{
374
-	struct node *map, *key;
375
-	struct type *ktype;
376
-
377
-	map = n->expr.args;
378
-
379
-	for (key = map->next; key; key = key->next) {
380
-		if (type_sizeof(key->sym->type) < 0)
381
-			return 0;
382
-	}
383
-
384
-	map->sym->type = type_map_of(global_map_ktype(n), n->sym->type);
385
-	return 0;
402
+	return map_ir_update(lval, prog);
386 403
 }
387 404
 
388 405
 static int global_assign_type_infer(const struct func *func, struct node *n)
389 406
 {
390 407
 	struct node *lval, *rval;
408
+	int err;
391 409
 
392 410
 	if (n->sym->type)
393 411
 		return 0;
@@ -406,10 +424,12 @@ static int global_assign_type_infer(const struct func *func, struct node *n)
406 424
 		/* TODO do we need assignment expressions? */
407 425
 		n->sym->type = &t_void;
408 426
 		
409
-		if (node_is(lval, "{}"))
410
-			return global_assign_type_infer_map(lval);
427
+		if (!node_is(lval, "{}"))
428
+			return 0;
411 429
 
412
-		return 0;
430
+		err = map_type_infer(lval->sym->func, lval);
431
+		if (err)
432
+			return err;
413 433
 	}
414 434
 
415 435
 	if (type_compatible(lval->sym->type, rval->sym->type))
@@ -458,7 +478,68 @@ static int global_binop_type_infer(const struct func *func, struct node *n)
458 478
 	return 0;
459 479
 }
460 480
 
461
-/* :binop */
481
+
482
+/* count() */
483
+
484
+struct type t_count = {
485
+	.ttype = T_SCALAR,
486
+
487
+	.scalar = {
488
+		.name = ":count",
489
+		.size = sizeof(unsigned long),
490
+		.is_signed = 0,
491
+	},
492
+
493
+	.aggregation = 1,
494
+};
495
+
496
+static int count_ir_post(const struct func *func, struct node *n,
497
+			 struct prog *prog)
498
+{
499
+	struct node *mapop = n->expr.args;
500
+
501
+	ir_emit_sym_to_reg(prog->ir, BPF_REG_0, mapop->sym);
502
+	ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 1), BPF_REG_0, 0);
503
+	ir_emit_reg_to_sym(prog->ir, mapop->sym, BPF_REG_0);
504
+
505
+	return map_ir_update(mapop, prog);
506
+}
507
+
508
+static int count_type_infer(const struct func *func, struct node *n)
509
+{
510
+	struct node *mapop;
511
+	struct type *t;
512
+
513
+	mapop = n->expr.args;
514
+
515
+	if (n->sym->type)
516
+		return 0;
517
+
518
+	n->sym->type = &t_void;
519
+
520
+	if (!mapop->sym->type) {
521
+		mapop->sym->type = &t_count;
522
+		return map_type_infer(mapop->sym->func, mapop);
523
+	}
524
+
525
+	return 0;
526
+}
527
+
528
+static int count_static_validate(const struct func *func, struct node *n)
529
+{
530
+	struct node *mapop;
531
+
532
+	mapop = n->expr.args;
533
+
534
+	if (node_is(mapop, "{}"))
535
+		return 0;
536
+
537
+	_e("%#N: aggregation target must be a map, %N is not.\n", n, mapop);
538
+	return -EINVAL;
539
+}
540
+
541
+
542
+/* quantize */
462 543
 
463 544
 static int global_quantize_type_infer(const struct func *func, struct node *n)
464 545
 {
@@ -640,13 +721,20 @@ static const struct func global_funcs[] = {
640 721
 	{
641 722
 		.name = "{}",
642 723
 		/* .type = t_map_func, */
643
-		.type_infer = global_map_type_infer,
644
-		.static_validate = global_map_static_validate,
724
+		.type_infer = map_type_infer,
725
+		.static_validate = map_static_validate,
645 726
 
646
-		.ir_pre  = global_map_ir_pre,
647
-		.ir_post = global_map_ir_post,
727
+		.ir_pre  = map_ir_pre,
728
+		.ir_post = map_ir_post,
648 729
 	},
730
+	{
731
+		.name = "count",
732
+		.type = &t_1arg_func,
733
+		.static_validate = count_static_validate,
734
+		.type_infer = count_type_infer,
649 735
 
736
+		.ir_post = count_ir_post,
737
+	},
650 738
 	{
651 739
 		.name = "pid",
652 740
 		.type = &t_pid_func,

+ 10 - 0
ir.c

@@ -180,9 +180,12 @@ static void __insn_dump(const struct bpf_insn insn, uint16_t dst, uint16_t src,
180 180
 
181 181
 	if (BPF_CLASS(insn.code) == BPF_LDX || BPF_CLASS(insn.code) == BPF_STX)
182 182
 		goto reg_src;
183
+	else if (BPF_CLASS(insn.code) == BPF_ST)
184
+		goto imm_src;
183 185
 
184 186
 	switch (BPF_SRC(insn.code)) {
185 187
 	case BPF_K:
188
+	imm_src:
186 189
 		fprintf(fp, "#%s0x%x", insn.imm < 0 ? "-" : "",
187 190
 			insn.imm < 0 ? -insn.imm : insn.imm);
188 191
 		break;
@@ -530,3 +533,10 @@ struct ir *ir_new(void)
530 533
 	ir->next_label = -1;
531 534
 	return ir;
532 535
 }
536
+
537
+
538
+
539
+int ir_generate_bpf(struct ir *ir)
540
+{
541
+	return 0;
542
+}

+ 2 - 0
ir.h

@@ -153,4 +153,6 @@ void ir_emit_bzero(struct ir *ir, ssize_t offset, size_t size);
153 153
 
154 154
 struct ir *ir_new(void);
155 155
 
156
+int ir_generate_bpf(struct ir *ir);
157
+
156 158
 #endif	/* _PLY_IR_H */

+ 34 - 11
ply.c

@@ -82,14 +82,21 @@ struct ctx *ctx_get(void)
82 82
 			  /* 	    node_ident("us"), */
83 83
 			  /* 	    node_expr("pid", NULL), */
84 84
 			  /* 	    NULL), */
85
-			  node_expr("=",
86
-				    node_expr("{}",
87
-					      node_ident("t"),
88
-					      node_expr("pid", NULL),
89
-					      node_num("0x10000000"),
85
+			  /* node_expr("=", */
86
+			  /* 	    node_expr("{}", */
87
+			  /* 		      node_ident("t"), */
88
+			  /* 		      node_expr("pid", NULL), */
89
+			  /* 		      node_num("0x10000000"), */
90
+			  /* 		      NULL), */
91
+			  /* 	    node_expr("time", NULL), */
92
+			  /* 	    NULL), */
93
+			  node_expr("count",
94
+			  	    node_expr("{}",
95
+			  		      node_ident("reads"),
96
+			  		      node_expr("pid", NULL),
97
+					      node_ident("arg0"),
90 98
 					      NULL),
91
-				    node_expr("time", NULL),
92
-				    NULL),
99
+			  	    NULL),
93 100
 			  /* node_expr("=", */
94 101
 			  /* 	    node_expr("{}", */
95 102
 			  /* 		      node_ident("reads"), */
@@ -213,6 +220,20 @@ int pass_ir_post(struct node *n, void *_prog)
213 220
 	return 0;
214 221
 }
215 222
 
223
+int run_walk(struct pass *pass, struct ctx *ctx)
224
+{
225
+	struct prog **prog;
226
+	int err;
227
+
228
+	for (prog = ctx->progs; *prog; prog++) {
229
+		err = node_walk((*prog)->ast, pass->pre, pass->post, *prog);
230
+		if (err)
231
+			return err;
232
+	}
233
+
234
+	return 0;
235
+}
236
+
216 237
 int run_ir(struct pass *pass, struct ctx *ctx)
217 238
 {
218 239
 	struct prog **progp;
@@ -241,13 +262,15 @@ int run_ir(struct pass *pass, struct ctx *ctx)
241 262
 	return 0;
242 263
 }
243 264
 
244
-int run_walk(struct pass *pass, struct ctx *ctx)
265
+int run_bpf(struct pass *pass, struct ctx *ctx)
245 266
 {
246
-	struct prog **prog;
267
+	struct prog **progp;
247 268
 	int err;
248 269
 
249
-	for (prog = ctx->progs; *prog; prog++) {
250
-		err = node_walk((*prog)->ast, pass->pre, pass->post, *prog);
270
+	for (progp = ctx->progs; *progp; progp++) {
271
+		struct prog *prog = *progp;
272
+
273
+		err = ir_generate_bpf(prog->ir);
251 274
 		if (err)
252 275
 			return err;
253 276
 	}

+ 4 - 2
type.c

@@ -31,8 +31,7 @@ static void type_dump_func(struct type *t, const char *name, FILE *fp)
31 31
 	struct tfield *arg;
32 32
 
33 33
 	type_dump(t->func.type, NULL, fp);
34
-	fprintf(fp, " %s(*\e[1m%s\e[0m)(",
35
-		t->func.aggregation ? "@" : "", name ? : "");
34
+	fprintf(fp, " (*\e[1m%s\e[0m)(", name ? : "");
36 35
 
37 36
 	if (!t->func.args) {
38 37
 		__faint(fp, t->func.vargs ? "..." : "void");
@@ -60,6 +59,9 @@ void type_dump(struct type *t, const char *name, FILE *fp)
60 59
 		goto print_name;
61 60
 	}
62 61
 
62
+	if (t->aggregation)
63
+		fputc('@', fp);
64
+
63 65
 	switch (t->ttype){
64 66
 	case T_VOID:
65 67
 		__faint(fp, "void");

+ 2 - 1
type.h

@@ -52,7 +52,6 @@ struct tfunc {
52 52
 	struct tfield *args;
53 53
 
54 54
 	int vargs:1;
55
-	int aggregation:1;
56 55
 };
57 56
 
58 57
 enum ttype {
@@ -78,6 +77,8 @@ struct type {
78 77
 		struct tstruct sou;
79 78
 		struct tfunc func;
80 79
 	};
80
+
81
+	int aggregation:1;
81 82
 };
82 83
 
83 84
 int type_equal     (struct type *a, struct type *b);