Browse code

bytecode: Introduce cli_bc_value to store the result of an operation. Implement More checking.

Török Edvin authored on 2009/07/07 23:38:56
Showing 3 changed files
... ...
@@ -31,16 +31,27 @@
31 31
 #include <string.h>
32 32
 
33 33
 typedef uint32_t operand_t;
34
+typedef uint16_t bbid_t;
35
+typedef uint16_t funcid_t;
34 36
 
35
-struct cli_bc_varop {
36
-    uint8_t numOps;
37
+struct cli_bc_callop {
37 38
     operand_t* ops;
39
+    uint8_t numOps;
40
+    funcid_t funcid;
38 41
 };
39 42
 
40 43
 struct branch {
41 44
     operand_t condition;
42
-    struct cli_bc_bb *br_true;
43
-    struct cli_bc_bb *br_false;
45
+    bbid_t br_true;
46
+    bbid_t br_false;
47
+};
48
+
49
+#define MAX_OP (operand_t)(~0u)
50
+#define CONSTANT_OP (MAX_OP-1)
51
+#define ARG_OP (MAX_OP-1)
52
+struct cli_bc_value {
53
+    uint64_t v;
54
+    operand_t ref;/* this has CONSTANT_OP value for constants, and ARG_op for arguments */
44 55
 };
45 56
 
46 57
 struct cli_bc_inst {
... ...
@@ -50,9 +61,9 @@ struct cli_bc_inst {
50 50
 	operand_t unaryop;
51 51
 	operand_t binop[2];
52 52
 	operand_t three[3];
53
-	struct cli_bc_varop ops;
53
+	struct cli_bc_callop ops;
54 54
 	struct branch branch;
55
-	struct cli_bc_bb *jump;
55
+	bbid_t jump;
56 56
     } u;
57 57
 };
58 58
 
... ...
@@ -64,9 +75,14 @@ struct cli_bc_bb {
64 64
 struct cli_bc_func {
65 65
     uint8_t numArgs;
66 66
     uint16_t numLocals;
67
+    uint32_t numInsts;
68
+    uint32_t numConstants;
67 69
     uint16_t numBB;
68 70
     uint16_t *types;
71
+    uint32_t insn_idx;
69 72
     struct cli_bc_bb *BB;
73
+    struct cli_bc_inst *allinsts;
74
+    struct cli_bc_value *values;
70 75
 };
71 76
 
72 77
 struct cli_bc_ctx {
... ...
@@ -124,15 +140,47 @@ static inline uint64_t readNumber(const unsigned char *p, unsigned *off, unsigne
124 124
     return n;
125 125
 }
126 126
 
127
-static inline uint64_t readOperand(unsigned char *p, unsigned *off, unsigned len, char *ok)
127
+static inline funcid_t readFuncID(struct cli_bc *bc, unsigned char *p,
128
+				  unsigned *off, unsigned len, char *ok)
128 129
 {
130
+    funcid_t id = readNumber(p, off, len, ok);
131
+    if (id >= bc->num_func) {
132
+	cli_errmsg("Called function out of range: %u >= %u\n", id, bc->num_func);
133
+	*ok = 0;
134
+	return ~0;
135
+    }
136
+    return id;
137
+}
138
+
139
+static inline operand_t readOperand(struct cli_bc_func *func, unsigned char *p,
140
+				    unsigned *off, unsigned len, char *ok)
141
+{
142
+    uint64_t v;
143
+    unsigned numValues = func->numArgs + func->numInsts + func->numConstants;
129 144
     if ((p[*off]&0xf0) == 0x40) {
130 145
 	p[*off] |= 0x20;
131
-	/* TODO: constant int operand needs to be added to constant table*/
132
-	return readNumber(p, off, len, ok);
146
+	/* TODO: unique constants */
147
+	func->values = cli_realloc2(func->values, (numValues+1)*sizeof(*func->values));
148
+	if (!func->values) {
149
+	    *ok = 0;
150
+	    return MAX_OP;
151
+	}
152
+	func->numConstants++;
153
+	func->values[numValues].v = readNumber(p, off, len, ok);
154
+	func->values[numValues].ref = CONSTANT_OP;
155
+	return numValues;
133 156
     }
134
-    return readNumber(p, off, len, ok);
157
+    v = readNumber(p, off, len, ok);
158
+    if (!*ok)
159
+	return MAX_OP;
160
+    if (v >= numValues) {
161
+	cli_errmsg("Operand index exceeds bounds: %u >= %u!\n", v, numValues);
162
+	*ok = 0;
163
+	return MAX_OP;
164
+    }
165
+    return v;
135 166
 }
167
+
136 168
 static inline unsigned readFixedNumber(const unsigned char *p, unsigned *off,
137 169
 				       unsigned len, char *ok, unsigned width)
138 170
 {
... ...
@@ -314,6 +362,31 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *bu
314 314
 	return CL_EMALFDB;
315 315
     }
316 316
     offset++;
317
+    func->numInsts = readNumber(buffer, &offset, len, &ok);
318
+    if (!ok ){
319
+	cli_errmsg("Invalid instructions count\n");
320
+	return CL_EMALFDB;
321
+    }
322
+    func->insn_idx = 0;
323
+    func->numConstants=0;
324
+    func->allinsts = cli_calloc(func->numInsts, sizeof(*func->allinsts));
325
+    if (!func->allinsts) {
326
+	cli_errmsg("Out of memory allocating instructions\n");
327
+	return CL_EMEM;
328
+    }
329
+    func->values = cli_calloc(func->numInsts+func->numArgs, sizeof(*func->values));
330
+    if (!func->values) {
331
+	cli_errmsg("Out of memory allocating values\n");
332
+	return CL_EMEM;
333
+    }
334
+    for (i=0;i<func->numArgs;i++) {
335
+	func->values[i].v = 0xdeadbeef;
336
+	func->values[i].ref = ARG_OP;
337
+    }
338
+    for(;i<func->numInsts+func->numArgs;i++) {
339
+	func->values[i].v = 0xdeadbeef;
340
+	func->values[i].ref = i-func->numArgs;
341
+    }
317 342
     func->numBB = readNumber(buffer, &offset, len, &ok);
318 343
     if (!ok) {
319 344
 	cli_errmsg("Invalid basic block count\n");
... ...
@@ -327,15 +400,15 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *bu
327 327
     return CL_SUCCESS;
328 328
 }
329 329
 
330
-static struct cli_bc_bb *readBBID(struct cli_bc_func *func, const unsigned char *buffer, unsigned *off, unsigned len, char *ok) {
330
+static bbid_t readBBID(struct cli_bc_func *func, const unsigned char *buffer, unsigned *off, unsigned len, char *ok) {
331 331
     unsigned id = readNumber(buffer, off, len, ok);
332 332
     if (!id || id >= func->numBB) {
333 333
 	cli_errmsg("Basic block ID out of range: %u\n", id);
334 334
 	*ok = 0;
335 335
     }
336 336
     if (!*ok)
337
-	return NULL;
338
-    return &func->BB[id];
337
+	return ~0;
338
+    return id;
339 339
 }
340 340
 
341 341
 static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char *buffer)
... ...
@@ -359,7 +432,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
359 359
     }
360 360
     offset = 1;
361 361
     BB->numInsts = 0;
362
-    BB->insts = NULL;
362
+    BB->insts = &bcfunc->allinsts[bcfunc->insn_idx];
363 363
     while (!last) {
364 364
 	unsigned numOp, i;
365 365
 	if (buffer[offset] == 'T') {
... ...
@@ -384,12 +457,12 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
384 384
 		inst.u.jump = readBBID(bcfunc, buffer, &offset, len, &ok);
385 385
 		break;
386 386
 	    case OP_BRANCH:
387
-		inst.u.branch.condition = readOperand(buffer, &offset, len, &ok);
387
+		inst.u.branch.condition = readOperand(bcfunc, buffer, &offset, len, &ok);
388 388
 		inst.u.branch.br_true = readBBID(bcfunc, buffer, &offset, len, &ok);
389 389
 		inst.u.branch.br_false = readBBID(bcfunc, buffer, &offset, len, &ok);
390 390
 		break;
391 391
 	    case OP_CALL_DIRECT:
392
-		numOp = readFixedNumber(buffer, &offset, len, &ok, 1)+1;
392
+		numOp = readFixedNumber(buffer, &offset, len, &ok, 1);
393 393
 		if (ok) {
394 394
 		    inst.u.ops.numOps = numOp;
395 395
 		    inst.u.ops.ops = cli_calloc(numOp, sizeof(*inst.u.ops.ops));
... ...
@@ -397,8 +470,9 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
397 397
 			cli_errmsg("Out of memory allocating operands\n");
398 398
 			return CL_EMALFDB;
399 399
 		    }
400
+		    inst.u.ops.funcid = readFuncID(bc, buffer, &offset, len, &ok);
400 401
 		    for (i=0;i<numOp;i++) {
401
-			inst.u.ops.ops[i] = readOperand(buffer, &offset, len, &ok);
402
+			inst.u.ops.ops[i] = readOperand(bcfunc, buffer, &offset, len, &ok);
402 403
 		    }
403 404
 		}
404 405
 		break;
... ...
@@ -406,16 +480,16 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
406 406
 		numOp = operand_counts[inst.opcode];
407 407
 		switch (numOp) {
408 408
 		    case 1:
409
-			inst.u.unaryop = readOperand(buffer, &offset, len, &ok);
409
+			inst.u.unaryop = readOperand(bcfunc, buffer, &offset, len, &ok);
410 410
 			break;
411 411
 		    case 2:
412
-			inst.u.binop[0] = readOperand(buffer, &offset, len, &ok);
413
-			inst.u.binop[1] = readOperand(buffer, &offset, len, &ok);
412
+			inst.u.binop[0] = readOperand(bcfunc, buffer, &offset, len, &ok);
413
+			inst.u.binop[1] = readOperand(bcfunc, buffer, &offset, len, &ok);
414 414
 			break;
415 415
 		    case 3:
416
-			inst.u.three[0] = readOperand(buffer, &offset, len, &ok);
417
-			inst.u.three[1] = readOperand(buffer, &offset, len, &ok);
418
-			inst.u.three[2] = readOperand(buffer, &offset, len, &ok);
416
+			inst.u.three[0] = readOperand(bcfunc, buffer, &offset, len, &ok);
417
+			inst.u.three[1] = readOperand(bcfunc, buffer, &offset, len, &ok);
418
+			inst.u.three[2] = readOperand(bcfunc, buffer, &offset, len, &ok);
419 419
 			break;
420 420
 		    default:
421 421
 			cli_errmsg("Opcode with too many operands: %u?\n", numOp);
... ...
@@ -427,13 +501,11 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
427 427
 	    cli_errmsg("Invalid instructions or operands\n");
428 428
 	    return CL_EMALFDB;
429 429
 	}
430
-	BB->insts = cli_realloc2(BB->insts, (++BB->numInsts)*sizeof(*BB->insts));
431
-	if (!BB->insts) {
432
-	    cli_errmsg("Unable to allocate memory for instruction %u\n", 
433
-		       BB->numInsts);
434
-	    return CL_EMEM;
430
+	if (bcfunc->insn_idx + BB->numInsts >= bcfunc->numInsts) {
431
+	    cli_errmsg("More instructions than declared in total!\n");
432
+	    return CL_EMALFDB;
435 433
 	}
436
-	BB->insts[BB->numInsts-1] = inst;
434
+	BB->insts[BB->numInsts++] = inst;
437 435
     }
438 436
     if (bb == bc->funcs[func].numBB-1) {
439 437
 	if (buffer[offset] != 'E') {
... ...
@@ -530,9 +602,10 @@ void cli_bytecode_destroy(struct cli_bc *bc)
530 530
 		if (operand_counts[i->opcode] > 3)
531 531
 		    free(i->u.ops.ops);
532 532
 	    }
533
-	    free(BB->insts);
534 533
 	}
535 534
 	free(f->BB);
535
+	free(f->allinsts);
536
+	free(f->values);
536 537
     }
537 538
     free(bc->funcs);
538 539
 }
... ...
@@ -26,6 +26,7 @@
26 26
 struct cli_dbio;
27 27
 struct cli_bc_ctx;
28 28
 struct cli_bc_func;
29
+struct cli_bc_value;
29 30
 
30 31
 struct cli_bc {
31 32
   unsigned verifier;
... ...
@@ -80,7 +80,7 @@ static const unsigned char operand_counts[] = {
80 80
   /* ADD -> XOR */
81 81
   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
82 82
   /* TRUNC -> ZEXT */
83
-  2, 2, 2,
83
+  1, 1, 1,
84 84
   /* BRANCH, JMP, RET */
85 85
   3, 1, 1,
86 86
   /* ICMP */