Procházet zdrojové kódy

basic vreg->r0-9 replacement

Tobias Waldekranz.com před 8 roky
rodič
revize
256174d880
3 změnil soubory, kde provedl 81 přidání a 33 odebrání
  1. 75 29
      ir.c
  2. 4 3
      ir.h
  3. 2 1
      ply.c

+ 75 - 29
ir.c

@@ -6,6 +6,7 @@
6 6
 #include <linux/bpf.h>
7 7
 
8 8
 #include "ir.h"
9
+#include "ply.h"
9 10
 #include "sym.h"
10 11
 #include "type.h"
11 12
 
@@ -225,11 +226,6 @@ void vinsn_dump(struct vinsn *vi, FILE *fp)
225 226
 		offset_dump(vi->label, fp);
226 227
 		fputc(':', fp);
227 228
 		return;
228
-	case VI_REG_GET:
229
-	case VI_REG_PUT:
230
-		fputs((vi->vitype == VI_REG_GET) ? "+ " : "- ", fp);
231
-		reg_dump(vi->reg, 0, fp);
232
-		return;
233 229
 	}
234 230
 }
235 231
 
@@ -245,9 +241,6 @@ void ir_dump(struct ir *ir, FILE *fp)
245 241
 		case VI_LDMAP:
246 242
 			fputc('\t', fp);
247 243
 			break;
248
-		case VI_REG_GET:
249
-		case VI_REG_PUT:
250
-			fputs("\e[2m", fp);
251 244
 		case VI_LABEL:
252 245
 		default:
253 246
 			break;
@@ -255,26 +248,6 @@ void ir_dump(struct ir *ir, FILE *fp)
255 248
 
256 249
 		vinsn_dump(vi, fp);
257 250
 
258
-		/* print multiple gets/puts on one line */
259
-		switch (vi->vitype) {
260
-		case VI_REG_GET:
261
-			for (; (vi + 1)->vitype == VI_REG_GET; vi++, i++) {
262
-				fputs(", ", fp);
263
-				reg_dump((vi + 1)->reg, 0, fp);
264
-			}
265
-			fputs("\e[0m", fp);
266
-			break;
267
-		case VI_REG_PUT:
268
-			for (; (vi + 1)->vitype == VI_REG_PUT; vi++, i++) {
269
-				fputs(", ", fp);
270
-				reg_dump((vi + 1)->reg, 0, fp);
271
-			}
272
-			fputs("\e[0m", fp);
273
-			break;
274
-		default:
275
-			break;
276
-		}
277
-
278 251
 		fputc('\n', fp);
279 252
 	}
280 253
 }
@@ -534,9 +507,82 @@ struct ir *ir_new(void)
534 507
 	return ir;
535 508
 }
536 509
 
510
+static void ir_bpf_vreg_replace(struct ir *ir, struct vinsn *last, int reg)
511
+{
512
+	struct vinsn *vi;
513
+
514
+	_d("ir_bpf_generate: v%d -> r%d\n", last->insn.src & ~vreg_base, reg);
515
+
516
+	for (vi = ir->vi; vi <= last; vi++) {
517
+		if (vi->vitype != VI_INSN)
518
+			continue;
519
+
520
+		if (vi->insn.dst == last->insn.src)
521
+			vi->insn.dst = reg;
522
+		if (vi->insn.src == last->insn.src)
523
+			vi->insn.src = reg;
524
+	}	
525
+}
537 526
 
538 527
 
539
-int ir_generate_bpf(struct ir *ir)
528
+int ir_bpf_registerize_one(struct ir *ir, struct vinsn *last)
540 529
 {
530
+	struct vinsn *vi;
531
+	uint16_t clean = 0x3ff;
532
+
533
+	for (vi = ir->vi; clean && (vi < last); vi++) {
534
+		if (vi->vitype != VI_INSN)
535
+			continue;
536
+
537
+		if (!(vi->insn.src & vreg_base))
538
+			clean &= ~(1 << vi->insn.src);
539
+		if (!(vi->insn.dst & vreg_base))
540
+			clean &= ~(1 << vi->insn.dst);
541
+		if (vi->insn.bpf.code == (BPF_JMP | BPF_CALL))
542
+			clean &= ~BPF_REG_CALLER_SAVE;
543
+	}
544
+
545
+	if (clean) {
546
+		int reg;
547
+
548
+		for (reg = BPF_REG_0; !(clean & 1); clean >>= 1, reg++);
549
+
550
+		ir_bpf_vreg_replace(ir, last, reg);
551
+		return 0;
552
+	}
553
+
554
+	/* TODO ir_bpf_vreg_spill(ir, last); */
555
+	return -1;
556
+}
557
+
558
+int ir_bpf_registerize(struct ir *ir)
559
+{
560
+	struct vinsn *vi;
561
+	int err = 0;
562
+
563
+	if (!ir->len)
564
+		return 0;
565
+	
566
+	for (vi = &ir->vi[ir->len - 1]; vi >= ir->vi; vi--) {
567
+		if (vi->vitype != VI_INSN)
568
+			continue;
569
+
570
+		if (vi->insn.src & vreg_base) {
571
+			err = ir_bpf_registerize_one(ir, vi);
572
+			if (err)
573
+				return err;
574
+		}
575
+	}
576
+	return err;
577
+}
578
+
579
+int ir_bpf_generate(struct ir *ir)
580
+{
581
+	int err;
582
+
583
+	err = ir_bpf_registerize(ir);
584
+	if (err)
585
+		return err;
586
+
541 587
 	return 0;
542 588
 }

+ 4 - 3
ir.h

@@ -53,6 +53,9 @@
53 53
 
54 54
 #define BPF_REG_BP BPF_REG_10
55 55
 
56
+/* r0 is return value and r1-r5 are used for arguments */
57
+#define BPF_REG_CALLER_SAVE 0x3f
58
+
56 59
 static inline int bpf_width(size_t size)
57 60
 {
58 61
 	switch (size) {
@@ -72,8 +75,6 @@ enum vitype {
72 75
 	VI_INSN,
73 76
 	VI_LDMAP,
74 77
 	VI_LABEL,
75
-	VI_REG_GET,
76
-	VI_REG_PUT,
77 78
 };
78 79
 
79 80
 struct vinsn {
@@ -153,6 +154,6 @@ void ir_emit_bzero(struct ir *ir, ssize_t offset, size_t size);
153 154
 
154 155
 struct ir *ir_new(void);
155 156
 
156
-int ir_generate_bpf(struct ir *ir);
157
+int ir_bpf_generate(struct ir *ir);
157 158
 
158 159
 #endif	/* _PLY_IR_H */

+ 2 - 1
ply.c

@@ -270,7 +270,7 @@ int run_bpf(struct pass *pass, struct ctx *ctx)
270 270
 	for (progp = ctx->progs; *progp; progp++) {
271 271
 		struct prog *prog = *progp;
272 272
 
273
-		err = ir_generate_bpf(prog->ir);
273
+		err = ir_bpf_generate(prog->ir);
274 274
 		if (err)
275 275
 			return err;
276 276
 	}
@@ -290,6 +290,7 @@ struct pass passes[] = {
290 290
 	{ .run = run_ir },
291 291
 	/* program flattened to vBPF instructions, now rewrite it to
292 292
 	 * fit into the actual hw/vm. */
293
+	{ .run = run_bpf },
293 294
 
294 295
 	/* BPF program ready */
295 296
 	{ NULL }