... | ... |
@@ -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 |
} |