Browse code

Add support for branches.

Török Edvin authored on 2009/06/29 21:01:01
Showing 2 changed files
... ...
@@ -30,18 +30,29 @@
30 30
 #include "readdb.h"
31 31
 #include <string.h>
32 32
 
33
+typedef uint32_t operand_t;
34
+
33 35
 struct cli_bc_varop {
34 36
     uint8_t numOps;
35
-    uint16_t* ops;
37
+    operand_t* ops;
38
+};
39
+
40
+struct branch {
41
+    operand_t condition;
42
+    struct cli_bc_bb *br_true;
43
+    struct cli_bc_bb *br_false;
36 44
 };
37 45
 
38 46
 struct cli_bc_inst {
39 47
     enum bc_opcode opcode;
40 48
     uint16_t type;
41 49
     union {
42
-	uint16_t unaryop;
43
-	uint16_t binop[2];
50
+	operand_t unaryop;
51
+	operand_t binop[2];
52
+	operand_t three[3];
44 53
 	struct cli_bc_varop ops;
54
+	struct branch branch;
55
+	struct cli_bc_bb *jump;
45 56
     } u;
46 57
 };
47 58
 
... ...
@@ -148,7 +159,7 @@ static inline unsigned readFixedNumber(const unsigned char *p, unsigned *off,
148 148
     return n;
149 149
 }
150 150
 
151
-static inline char *readData(const unsigned char *p, unsigned *off, unsigned len, char *ok)
151
+static inline unsigned char *readData(const unsigned char *p, unsigned *off, unsigned len, char *ok, unsigned *datalen)
152 152
 {
153 153
     unsigned char *dat, *q;
154 154
     unsigned l, newoff, i;
... ...
@@ -184,10 +195,22 @@ static inline char *readData(const unsigned char *p, unsigned *off, unsigned len
184 184
 	*q++ = v;
185 185
     }
186 186
     *off = newoff;
187
+    *datalen = l;
187 188
     return dat;
188 189
 }
189 190
 
190
-static int parseHeader(struct cli_bc *bc, char *buffer)
191
+static inline char *readString(const unsigned char *p, unsigned *off, unsigned len, char *ok)
192
+{
193
+    unsigned stringlen;
194
+    char *str = (char*)readData(p, off, len, ok, &stringlen);
195
+    if (*ok && stringlen && str[stringlen-1] != '\0') {
196
+	free(str);
197
+	*ok = 0;
198
+	return NULL;
199
+    }
200
+    return str;
201
+}
202
+static int parseHeader(struct cli_bc *bc, unsigned char *buffer)
191 203
 {
192 204
     uint64_t magic1;
193 205
     unsigned magic2;
... ...
@@ -198,7 +221,7 @@ static int parseHeader(struct cli_bc *bc, char *buffer)
198 198
 	return CL_EMALFDB;
199 199
     }
200 200
     offset = sizeof(BC_HEADER)-1;
201
-    len = strlen(buffer);
201
+    len = strlen((const char*)buffer);
202 202
     flevel = readNumber(buffer, &offset, len, &ok);
203 203
     if (!ok) {
204 204
 	cli_errmsg("Unable to parse functionality level in bytecode header\n");
... ...
@@ -210,15 +233,15 @@ static int parseHeader(struct cli_bc *bc, char *buffer)
210 210
     }
211 211
     // Optimistic parsing, check for error only at the end.
212 212
     bc->verifier = readNumber(buffer, &offset, len, &ok);
213
-    bc->sigmaker = readData(buffer, &offset, len, &ok);
213
+    bc->sigmaker = readString(buffer, &offset, len, &ok);
214 214
     bc->id = readNumber(buffer, &offset, len, &ok);
215 215
     bc->metadata.maxStack = readNumber(buffer, &offset, len, &ok);
216 216
     bc->metadata.maxMem = readNumber(buffer, &offset, len, &ok);
217 217
     bc->metadata.maxTime = readNumber(buffer, &offset, len, &ok);
218
-    bc->metadata.targetExclude = readData(buffer, &offset, len, &ok);
218
+    bc->metadata.targetExclude = readString(buffer, &offset, len, &ok);
219 219
     bc->num_func = readNumber(buffer, &offset, len, &ok);
220 220
     if (!ok) {
221
-	cli_errmsg("Invalid bytecode header\n", offset);
221
+	cli_errmsg("Invalid bytecode header at %u\n", offset);
222 222
 	return CL_EMALFDB;
223 223
     }
224 224
     magic1 = readNumber(buffer, &offset, len, &ok);
... ...
@@ -243,7 +266,7 @@ static int parseHeader(struct cli_bc *bc, char *buffer)
243 243
     return CL_SUCCESS;
244 244
 }
245 245
 
246
-static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, char *buffer)
246
+static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *buffer)
247 247
 {
248 248
     char ok=1;
249 249
     unsigned offset, len, all_locals=0, i;
... ...
@@ -255,7 +278,7 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, char *buffer)
255 255
 	return CL_EMALFDB;
256 256
     }
257 257
     func = &bc->funcs[fn];
258
-    len = strlen(buffer);
258
+    len = strlen((const char*)buffer);
259 259
 
260 260
     if (buffer[0] != 'A') {
261 261
 	cli_errmsg("Invalid function arguments header: %c\n", buffer[0]);
... ...
@@ -304,20 +327,32 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, char *buffer)
304 304
     return CL_SUCCESS;
305 305
 }
306 306
 
307
-static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, char *buffer)
307
+static struct cli_bc_bb *readBBID(struct cli_bc_func *func, const unsigned char *buffer, unsigned *off, unsigned len, char *ok) {
308
+    unsigned id = readNumber(buffer, off, len, ok);
309
+    if (!id || id >= func->numBB) {
310
+	cli_errmsg("Basic block ID out of range: %u\n", id);
311
+	*ok = 0;
312
+    }
313
+    if (!*ok)
314
+	return NULL;
315
+    return &func->BB[id];
316
+}
317
+
318
+static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char *buffer)
308 319
 {
309 320
     char ok=1;
310 321
     unsigned offset, len, last = 0;
311 322
     struct cli_bc_bb *BB;
323
+    struct cli_bc_func *bcfunc = &bc->funcs[func];
312 324
     struct cli_bc_inst inst;
313 325
 
314
-    if (bb >= bc->funcs[func].numBB) {
326
+    if (bb >= bcfunc->numBB) {
315 327
 	cli_errmsg("Found too many basic blocks\n");
316 328
 	return CL_EMALFDB;
317 329
     }
318 330
 
319
-    BB = &bc->funcs[func].BB[bb];
320
-    len = strlen(buffer);
331
+    BB = &bcfunc->BB[bb];
332
+    len = strlen((const char*) buffer);
321 333
     if (buffer[0] != 'B') {
322 334
 	cli_errmsg("Invalid basic block header: %c\n", buffer[0]);
323 335
 	return CL_EMALFDB;
... ...
@@ -344,26 +379,42 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, char *buffer)
344 344
 	    cli_errmsg("Invalid opcode: %u\n", inst.opcode);
345 345
 	    return CL_EMALFDB;
346 346
 	}
347
-	numOp = operand_counts[inst.opcode];
348
-	switch (numOp) {
349
-	    case 1:
350
-		inst.u.unaryop = readOperand(buffer, &offset, len, &ok);
347
+	switch (inst.opcode) {
348
+	    case OP_JMP:
349
+		inst.u.jump = readBBID(bcfunc, buffer, &offset, len, &ok);
351 350
 		break;
352
-	    case 2:
353
-		inst.u.binop[0] = readOperand(buffer, &offset, len, &ok);
354
-		inst.u.binop[1] = readOperand(buffer, &offset, len, &ok);
351
+	    case OP_BRANCH:
352
+		inst.u.branch.condition = readOperand(buffer, &offset, len, &ok);
353
+		inst.u.branch.br_true = readBBID(bcfunc, buffer, &offset, len, &ok);
354
+		inst.u.branch.br_false = readBBID(bcfunc, buffer, &offset, len, &ok);
355 355
 		break;
356 356
 	    default:
357
-		inst.u.ops.numOps = numOp;
358
-		inst.u.ops.ops = cli_calloc(numOp, sizeof(*inst.u.ops.ops));
359
-		if (!inst.u.ops.ops) {
360
-		    cli_errmsg("Out of memory allocating operands\n");
361
-		    return CL_EMALFDB;
362
-		}
363
-		for (i=0;i<numOp;i++) {
364
-		    inst.u.ops.ops[i] = readOperand(buffer, &offset, len, &ok);
357
+		numOp = operand_counts[inst.opcode];
358
+		switch (numOp) {
359
+		    case 1:
360
+			inst.u.unaryop = readOperand(buffer, &offset, len, &ok);
361
+			break;
362
+		    case 2:
363
+			inst.u.binop[0] = readOperand(buffer, &offset, len, &ok);
364
+			inst.u.binop[1] = readOperand(buffer, &offset, len, &ok);
365
+			break;
366
+		    case 3:
367
+			inst.u.three[0] = readOperand(buffer, &offset, len, &ok);
368
+			inst.u.three[1] = readOperand(buffer, &offset, len, &ok);
369
+			inst.u.three[2] = readOperand(buffer, &offset, len, &ok);
370
+			break;
371
+		    default:
372
+			inst.u.ops.numOps = numOp;
373
+			inst.u.ops.ops = cli_calloc(numOp, sizeof(*inst.u.ops.ops));
374
+			if (!inst.u.ops.ops) {
375
+			    cli_errmsg("Out of memory allocating operands\n");
376
+			    return CL_EMALFDB;
377
+			}
378
+			for (i=0;i<numOp;i++) {
379
+			    inst.u.ops.ops[i] = readOperand(buffer, &offset, len, &ok);
380
+			}
381
+			break;
365 382
 		}
366
-		break;
367 383
 	}
368 384
 	if (!ok) {
369 385
 	    cli_errmsg("Invalid instructions or operands\n");
... ...
@@ -415,7 +466,7 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio)
415 415
 	cli_chomp(buffer);
416 416
 	switch (state) {
417 417
 	    case PARSE_BC_HEADER:
418
-		rc = parseHeader(bc, buffer);
418
+		rc = parseHeader(bc, (unsigned char*)buffer);
419 419
 		if (rc == CL_BREAK) /* skip */
420 420
 		    return CL_SUCCESS;
421 421
 		if (rc != CL_SUCCESS)
... ...
@@ -423,14 +474,14 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio)
423 423
 		state = PARSE_FUNC_HEADER;
424 424
 		break;
425 425
 	    case PARSE_FUNC_HEADER:
426
-		rc = parseFunctionHeader(bc, current_func, buffer);
426
+		rc = parseFunctionHeader(bc, current_func, (unsigned char*)buffer);
427 427
 		if (rc != CL_SUCCESS)
428 428
 		    return rc;
429 429
 		bb = 0;
430 430
 		state = PARSE_BB;
431 431
 		break;
432 432
 	    case PARSE_BB:
433
-		rc = parseBB(bc, current_func, bb++, buffer);
433
+		rc = parseBB(bc, current_func, bb++, (unsigned char*)buffer);
434 434
 		if (rc != CL_SUCCESS)
435 435
 		    return rc;
436 436
 		if (bb >= bc->funcs[current_func].numBB) {
... ...
@@ -462,7 +513,7 @@ void cli_bytecode_destroy(struct cli_bc *bc)
462 462
 	    struct cli_bc_bb *BB = &f->BB[j];
463 463
 	    for(k=0;k<BB->numInsts;k++) {
464 464
 		struct cli_bc_inst *i = &BB->insts[k];
465
-		if (operand_counts[i->opcode] > 2)
465
+		if (operand_counts[i->opcode] > 3)
466 466
 		    free(i->u.ops.ops);
467 467
 	    }
468 468
 	    free(BB->insts);
... ...
@@ -49,6 +49,9 @@ enum bc_opcode {
49 49
   OP_TRUNC,
50 50
   OP_SEXT,
51 51
   OP_ZEXT,
52
+
53
+  OP_BRANCH,
54
+  OP_JMP,
52 55
   OP_RET,
53 56
 
54 57
   OP_ICMP_EQ,
... ...
@@ -71,8 +74,8 @@ static const unsigned char operand_counts[] = {
71 71
   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
72 72
   /* TRUNC -> ZEXT */
73 73
   2, 2, 2,
74
-  /* RET */
75
-  1,
74
+  /* BRANCH, JMP, RET */
75
+  3, 1, 1,
76 76
   /* ICMP */
77 77
   2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
78 78
   /* SELECT */