... | ... |
@@ -1542,6 +1542,25 @@ static inline int64_t ptr_compose(int32_t id, uint32_t offset) |
1542 | 1542 |
return (i << 32) | offset; |
1543 | 1543 |
} |
1544 | 1544 |
|
1545 |
+static inline int get_geptypesize(const struct cli_bc *bc, uint16_t tid) |
|
1546 |
+{ |
|
1547 |
+ const struct cli_bc_type *ty; |
|
1548 |
+ if (tid >= bc->num_types+65) { |
|
1549 |
+ cli_errmsg("bytecode: typeid out of range %u >= %u\n", tid, bc->num_types); |
|
1550 |
+ return -1; |
|
1551 |
+ } |
|
1552 |
+ if (tid <= 64) { |
|
1553 |
+ cli_errmsg("bytecode: invalid type for gep (%u)\n", tid); |
|
1554 |
+ return -1; |
|
1555 |
+ } |
|
1556 |
+ ty = &bc->types[tid - 65]; |
|
1557 |
+ if (ty->kind != DPointerType) { |
|
1558 |
+ cli_errmsg("bytecode: invalid gep type, must be pointer: %u\n", tid); |
|
1559 |
+ return -1; |
|
1560 |
+ } |
|
1561 |
+ return typesize(bc, ty->containedTypes[0]); |
|
1562 |
+} |
|
1563 |
+ |
|
1545 | 1564 |
static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) |
1546 | 1565 |
{ |
1547 | 1566 |
unsigned i, j, k; |
... | ... |
@@ -1736,6 +1755,16 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) |
1736 | 1736 |
MAPPTR(inst->u.unaryop); |
1737 | 1737 |
break; |
1738 | 1738 |
case OP_BC_GEP1: |
1739 |
+ if (bcfunc->types[inst->u.binop[1]]&0x8000) { |
|
1740 |
+ cli_errmsg("bytecode: gep1 of alloca is not allowed\n"); |
|
1741 |
+ return CL_EBYTECODE; |
|
1742 |
+ } |
|
1743 |
+ MAP(inst->u.three[1]); |
|
1744 |
+ MAP(inst->u.three[2]); |
|
1745 |
+ inst->u.three[0] = get_geptypesize(bc, inst->u.three[0]); |
|
1746 |
+ if (inst->u.three[0] == -1) |
|
1747 |
+ return CL_EBYTECODE; |
|
1748 |
+ break; |
|
1739 | 1749 |
case OP_BC_GEPZ: |
1740 | 1750 |
/*three[0] is the type*/ |
1741 | 1751 |
if (bcfunc->types[inst->u.three[1]]&0x8000) |
... | ... |
@@ -1756,11 +1785,10 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) |
1756 | 1756 |
MAPPTR(inst->u.three[1]); |
1757 | 1757 |
MAP(inst->u.three[2]); |
1758 | 1758 |
break; |
1759 |
+ case OP_BC_RET_VOID: |
|
1759 | 1760 |
case OP_BC_ISBIGENDIAN: |
1760 |
- /*TODO */ |
|
1761 |
- break; |
|
1762 | 1761 |
case OP_BC_ABORT: |
1763 |
- /* TODO */ |
|
1762 |
+ /* no operands */ |
|
1764 | 1763 |
break; |
1765 | 1764 |
case OP_BC_BSWAP16: |
1766 | 1765 |
case OP_BC_BSWAP32: |
... | ... |
@@ -1768,7 +1796,11 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) |
1768 | 1768 |
MAP(inst->u.unaryop); |
1769 | 1769 |
break; |
1770 | 1770 |
case OP_BC_PTRDIFF32: |
1771 |
- /*TODO */ |
|
1771 |
+ MAPPTR(inst->u.binop[0]); |
|
1772 |
+ MAPPTR(inst->u.binop[1]); |
|
1773 |
+ break; |
|
1774 |
+ case OP_BC_PTRTOINT64: |
|
1775 |
+ MAPPTR(inst->u.unaryop); |
|
1772 | 1776 |
break; |
1773 | 1777 |
default: |
1774 | 1778 |
cli_dbgmsg("Unhandled opcode: %d\n", inst->opcode); |
... | ... |
@@ -100,7 +100,7 @@ static always_inline int jump(const struct cli_bc_func *func, uint16_t bbid, str |
100 | 100 |
return 0; |
101 | 101 |
} |
102 | 102 |
|
103 |
-#define STACK_CHUNKSIZE 16384 |
|
103 |
+#define STACK_CHUNKSIZE 32768 |
|
104 | 104 |
|
105 | 105 |
struct stack_chunk { |
106 | 106 |
struct stack_chunk *prev; |
... | ... |
@@ -485,6 +485,18 @@ static inline int64_t ptr_compose(int32_t id, uint32_t offset) |
485 | 485 |
return (i << 32) | offset; |
486 | 486 |
} |
487 | 487 |
|
488 |
+static inline int32_t ptr_diff32(int64_t ptr1, int64_t ptr2) |
|
489 |
+{ |
|
490 |
+ int32_t ptrid1 = ptr1 >> 32; |
|
491 |
+ int32_t ptrid2 = ptr2 >> 32; |
|
492 |
+ if (ptrid1 != ptrid2) { |
|
493 |
+ bcfail("difference of pointers not pointing to same object!", ptrid1, ptrid2, __FILE__, __LINE__); |
|
494 |
+ /* invalid diff */ |
|
495 |
+ return 0x40000000; |
|
496 |
+ } |
|
497 |
+ return (uint32_t)ptr1 - (uint32_t)ptr2; |
|
498 |
+} |
|
499 |
+ |
|
488 | 500 |
static inline int64_t ptr_register_stack(struct ptr_infos *infos, |
489 | 501 |
unsigned char *values, |
490 | 502 |
uint32_t off, uint32_t size) |
... | ... |
@@ -643,7 +655,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
643 | 643 |
if (tv1.tv_sec > timeout.tv_sec || |
644 | 644 |
(tv1.tv_sec == timeout.tv_sec && |
645 | 645 |
tv1.tv_usec > timeout.tv_usec)) { |
646 |
- cli_warnmsg("Bytecode run timed out in interpreter\n"); |
|
646 |
+ cli_warnmsg("Bytecode run timed out in interpreter after %u opcodes\n", pc); |
|
647 | 647 |
stop = CL_ETIMEOUT; |
648 | 648 |
break; |
649 | 649 |
} |
... | ... |
@@ -948,8 +960,8 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
948 | 948 |
case OP_BC_COPY*5+4: |
949 | 949 |
{ |
950 | 950 |
uint64_t op; |
951 |
- READ32(op, BINOP(0)); |
|
952 |
- WRITE32(BINOP(1), op); |
|
951 |
+ READ64(op, BINOP(0)); |
|
952 |
+ WRITE64(BINOP(1), op); |
|
953 | 953 |
break; |
954 | 954 |
} |
955 | 955 |
|
... | ... |
@@ -1111,6 +1123,41 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
1111 | 1111 |
WRITE64(inst->dest, cbswap64(arg1)); |
1112 | 1112 |
break; |
1113 | 1113 |
} |
1114 |
+ DEFINE_OP(OP_BC_PTRDIFF32) { |
|
1115 |
+ int64_t ptr1, ptr2; |
|
1116 |
+ if (BINOP(0)&0x40000000) |
|
1117 |
+ ptr1 = ptr_compose(stackid, BINOP(0)&0xbfffffff); |
|
1118 |
+ else |
|
1119 |
+ READ64(ptr1, BINOP(0)); |
|
1120 |
+ if (BINOP(1)&0x40000000) |
|
1121 |
+ ptr2 = ptr_compose(stackid, BINOP(1)&0xbfffffff); |
|
1122 |
+ else |
|
1123 |
+ READ64(ptr2, BINOP(1)); |
|
1124 |
+ WRITE32(inst->dest, ptr_diff32(ptr1, ptr2)); |
|
1125 |
+ break; |
|
1126 |
+ } |
|
1127 |
+ DEFINE_OP(OP_BC_PTRTOINT64) { |
|
1128 |
+ int64_t ptr; |
|
1129 |
+ if (inst->u.unaryop&0x40000000) |
|
1130 |
+ ptr = ptr_compose(stackid, inst->u.unaryop&0xbfffffff); |
|
1131 |
+ else |
|
1132 |
+ READ64(ptr, BINOP(0)); |
|
1133 |
+ WRITE64(inst->dest, ptr); |
|
1134 |
+ break; |
|
1135 |
+ } |
|
1136 |
+ DEFINE_OP(OP_BC_GEP1) { |
|
1137 |
+ int64_t ptr; |
|
1138 |
+ if (!(inst->interp_op%5)) { |
|
1139 |
+ int32_t off; |
|
1140 |
+ READ32(off, inst->u.three[2]); |
|
1141 |
+ WRITE64(inst->dest, ptr_compose(stackid, |
|
1142 |
+ inst->u.three[1]+off)); |
|
1143 |
+ } else { |
|
1144 |
+ READ64(ptr, inst->u.three[1]); |
|
1145 |
+ WRITE64(inst->dest, ptr); |
|
1146 |
+ } |
|
1147 |
+ break; |
|
1148 |
+ } |
|
1114 | 1149 |
/* TODO: implement OP_BC_GEP1, OP_BC_GEP2, OP_BC_GEPN */ |
1115 | 1150 |
default: |
1116 | 1151 |
cli_errmsg("Opcode %u of type %u is not implemented yet!\n", |
... | ... |
@@ -1128,8 +1175,8 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
1128 | 1128 |
gettimeofday(&tv1, NULL); |
1129 | 1129 |
tv1.tv_sec -= tv0.tv_sec; |
1130 | 1130 |
tv1.tv_usec -= tv0.tv_usec; |
1131 |
- cli_dbgmsg("intepreter bytecode run finished in %luus\n", |
|
1132 |
- tv1.tv_sec*1000000 + tv1.tv_usec); |
|
1131 |
+ cli_dbgmsg("intepreter bytecode run finished in %luus, after executing %u opcodes\n", |
|
1132 |
+ tv1.tv_sec*1000000 + tv1.tv_usec, pc); |
|
1133 | 1133 |
} |
1134 | 1134 |
|
1135 | 1135 |
cli_stack_destroy(&stack); |
... | ... |
@@ -982,6 +982,7 @@ public: |
982 | 982 |
case OP_BC_COPY: |
983 | 983 |
case OP_BC_RET: |
984 | 984 |
case OP_BC_PTRDIFF32: |
985 |
+ case OP_BC_PTRTOINT64: |
|
985 | 986 |
// these instructions represents operands differently |
986 | 987 |
break; |
987 | 988 |
default: |
... | ... |
@@ -1333,6 +1334,13 @@ public: |
1333 | 1333 |
Store(inst->dest, R); |
1334 | 1334 |
break; |
1335 | 1335 |
} |
1336 |
+ case OP_BC_PTRTOINT64: |
|
1337 |
+ { |
|
1338 |
+ Value *P1 = convertOperand(func, inst, inst->u.unaryop); |
|
1339 |
+ P1 = Builder.CreatePtrToInt(P1, Type::getInt64Ty(Context)); |
|
1340 |
+ Store(inst->dest, P1); |
|
1341 |
+ break; |
|
1342 |
+ } |
|
1336 | 1343 |
default: |
1337 | 1344 |
errs() << MODULE << "JIT doesn't implement opcode " << |
1338 | 1345 |
inst->opcode << " yet!\n"; |
... | ... |
@@ -87,6 +87,7 @@ enum bc_opcode { |
87 | 87 |
OP_BC_BSWAP32, |
88 | 88 |
OP_BC_BSWAP64, |
89 | 89 |
OP_BC_PTRDIFF32, |
90 |
+ OP_BC_PTRTOINT64, |
|
90 | 91 |
OP_BC_INVALID /* last */ |
91 | 92 |
}; |
92 | 93 |
|
... | ... |
@@ -112,8 +113,8 @@ static const unsigned char operand_counts[] = { |
112 | 112 |
3, 3, 3, 3, |
113 | 113 |
/* OP_BC_ISBIGENDIAN */ |
114 | 114 |
0, |
115 |
- /* OP_BC_ABORT, OP_BSWAP*, OP_PTRDIFF32 */ |
|
116 |
- 0, 1, 1, 1, 2 |
|
115 |
+ /* OP_BC_ABORT, OP_BSWAP*, OP_PTRDIFF32, OP_PTRINT64 */ |
|
116 |
+ 0, 1, 1, 1, 2, 1 |
|
117 | 117 |
}; |
118 | 118 |
|
119 | 119 |
enum bc_global { |