Browse code

clambc: added diagnostic tools for bytecode IR clambc: added option to print bytecode IR TODO: add diagnostic functions to win32 project

Conflicts:

shared/optparser.c

Kevin Lin authored on 2014/05/23 03:30:03
Showing 6 changed files
... ...
@@ -56,6 +56,7 @@ static void help(void)
56 56
     printf("    --version              -V         Show version\n");
57 57
     printf("    --info                 -i         Print information about bytecode\n");
58 58
     printf("    --printsrc             -p         Print bytecode source\n");
59
+    printf("    --printbcir            -c         Print bytecode IR\n");
59 60
     printf("    --trace <level>                   Set bytecode trace level 0..7 (default 7)\n");
60 61
     printf("    --no-trace-showsource             Don't show source line during tracing\n");
61 62
     printf("    file                              file to test\n");
... ...
@@ -328,6 +329,10 @@ int main(int argc, char *argv[])
328 328
 	cli_bytecode_describe(bc);
329 329
     } else if (optget(opts, "printsrc")->enabled) {
330 330
         print_src(opts->filename[0]);
331
+    } else if (optget(opts, "printbcir")->enabled) {
332
+        cli_bytetype_describe(bc);
333
+        cli_bytevalue_describe(bc, 0);
334
+        cli_bytefunc_describe(bc, 0);
331 335
     } else {
332 336
 	cli_ctx cctx;
333 337
 	struct cl_engine *engine = cl_engine_new();
... ...
@@ -1405,7 +1405,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
1405 1405
 	}
1406 1406
 	bcfunc->dbgnodes = cli_malloc(num*sizeof(*bcfunc->dbgnodes));
1407 1407
 	if (!bcfunc->dbgnodes) {
1408
-        cli_errmsg("Unable to allocate memory for dbg nodes: %s\n", num*sizeof(*bcfunc->dbgnodes));
1408
+        cli_errmsg("Unable to allocate memory for dbg nodes: %u\n", num*sizeof(*bcfunc->dbgnodes));
1409 1409
 	    return CL_EMEM;
1410 1410
     }
1411 1411
 	for (i=0;i<num;i++) {
... ...
@@ -3027,3 +3027,487 @@ void cli_bytecode_describe(const struct cli_bc *bc)
3027 3027
     }
3028 3028
     printf("\n");
3029 3029
 }
3030
+
3031
+const char *bc_tystr[] = {
3032
+    "DFunctionType",
3033
+    "DPointerType",
3034
+    "DStructType",
3035
+    "DPackedStructType",
3036
+    "DArrayType"
3037
+};
3038
+
3039
+const char *bc_opstr[] = {
3040
+    "OP_BC_NULL",
3041
+    "OP_BC_ADD", /* =1*/
3042
+    "OP_BC_SUB",
3043
+    "OP_BC_MUL",
3044
+    "OP_BC_UDIV",
3045
+    "OP_BC_SDIV",
3046
+    "OP_BC_UREM",
3047
+    "OP_BC_SREM",
3048
+    "OP_BC_SHL",
3049
+    "OP_BC_LSHR",
3050
+    "OP_BC_ASHR",
3051
+    "OP_BC_AND",
3052
+    "OP_BC_OR",
3053
+    "OP_BC_XOR",
3054
+
3055
+    "OP_BC_TRUNC",
3056
+    "OP_BC_SEXT",
3057
+    "OP_BC_ZEXT",
3058
+
3059
+    "OP_BC_BRANCH",
3060
+    "OP_BC_JMP",
3061
+    "OP_BC_RET",
3062
+    "OP_BC_RET_VOID",
3063
+
3064
+    "OP_BC_ICMP_EQ",
3065
+    "OP_BC_ICMP_NE",
3066
+    "OP_BC_ICMP_UGT",
3067
+    "OP_BC_ICMP_UGE",
3068
+    "OP_BC_ICMP_ULT",
3069
+    "OP_BC_ICMP_ULE",
3070
+    "OP_BC_ICMP_SGT",
3071
+    "OP_BC_ICMP_SGE",
3072
+    "OP_BC_ICMP_SLE",
3073
+    "OP_BC_ICMP_SLT",
3074
+    "OP_BC_SELECT",
3075
+    "OP_BC_CALL_DIRECT",
3076
+    "OP_BC_CALL_API",
3077
+    "OP_BC_COPY",
3078
+    "OP_BC_GEP1",
3079
+    "OP_BC_GEPZ",
3080
+    "OP_BC_GEPN",
3081
+    "OP_BC_STORE",
3082
+    "OP_BC_LOAD",
3083
+    "OP_BC_MEMSET",
3084
+    "OP_BC_MEMCPY",
3085
+    "OP_BC_MEMMOVE",
3086
+    "OP_BC_MEMCMP",
3087
+    "OP_BC_ISBIGENDIAN",
3088
+    "OP_BC_ABORT",
3089
+    "OP_BC_BSWAP16",
3090
+    "OP_BC_BSWAP32",
3091
+    "OP_BC_BSWAP64",
3092
+    "OP_BC_PTRDIFF32",
3093
+    "OP_BC_PTRTOINT64",
3094
+    "OP_BC_INVALID" /* last */
3095
+};
3096
+
3097
+extern unsigned cli_numapicalls;
3098
+static void cli_bytetype_helper(const struct cli_bc *bc, unsigned tid)
3099
+{
3100
+    unsigned i, j;
3101
+
3102
+    if (tid & 0x8000) {
3103
+        printf("alloc ");
3104
+        tid &= 0x7fff;
3105
+    }
3106
+
3107
+    if (tid < 65) {
3108
+        printf("i%d", tid);
3109
+        return;
3110
+    }
3111
+
3112
+    i = tid - 65;
3113
+    const struct cli_bc_type *ty = &bc->types[i];
3114
+
3115
+    switch (ty->kind) {
3116
+    case DFunctionType:
3117
+        cli_bytetype_helper(bc, ty->containedTypes[0]);
3118
+        printf(" func ( ");
3119
+        for (j = 1; j < ty->numElements; ++j) {
3120
+            cli_bytetype_helper(bc, ty->containedTypes[0]);
3121
+            printf(" ");
3122
+        }
3123
+        printf(")");
3124
+        break;
3125
+    case DPointerType:
3126
+        cli_bytetype_helper(bc, ty->containedTypes[0]);
3127
+        printf("*");
3128
+        break;
3129
+    case DStructType:
3130
+    case DPackedStructType:
3131
+        printf("{ ");
3132
+        for (j = 0; j < ty->numElements; ++j) {
3133
+            cli_bytetype_helper(bc, ty->containedTypes[0]);
3134
+            printf(" ");
3135
+        }
3136
+        printf("}");
3137
+        break;
3138
+    case DArrayType:
3139
+        printf("[");
3140
+        printf("%d x ", ty->numElements);
3141
+        cli_bytetype_helper(bc, ty->containedTypes[0]);
3142
+        printf("]");
3143
+        break;
3144
+    default:
3145
+        printf("unhandled type kind %d, cannot parse", ty->kind);
3146
+        break;
3147
+    }
3148
+
3149
+}
3150
+
3151
+void cli_bytetype_describe(const struct cli_bc *bc)
3152
+{
3153
+    unsigned i, tid;
3154
+
3155
+    printf("found %d extra types of %d total, starting at tid %d\n", 
3156
+           bc->num_types, 64+bc->num_types, bc->start_tid);
3157
+
3158
+    printf("TID  KIND                INTERNAL\n");
3159
+    printf("------------------------------------------------------------------------\n");
3160
+    for (i = 0, tid = 65; i < bc->num_types-1; ++i, ++tid) {
3161
+        printf("%3d: %-20s", tid, bc_tystr[bc->types[i].kind]);
3162
+        cli_bytetype_helper(bc, tid);
3163
+        printf("\n");
3164
+    }
3165
+    printf("------------------------------------------------------------------------\n");
3166
+}
3167
+
3168
+void cli_bytevalue_describe(const struct cli_bc *bc, unsigned funcid)
3169
+{
3170
+    unsigned i, j, total = 0;
3171
+    const struct cli_bc_func *func;
3172
+
3173
+    if (funcid >= bc->num_func) {
3174
+        printf("bytecode diagnostic: funcid [%u] outside byecode numfuncs [%u]\n",
3175
+               funcid, bc->num_func);
3176
+        return;
3177
+    }
3178
+    // globals
3179
+    printf("found a total of %d globals\n", bc->num_globals);
3180
+    printf("GID  ID    VALUE\n");
3181
+    printf("------------------------------------------------------------------------\n");
3182
+    for (i = 0; i < bc->num_globals; ++i) {
3183
+        printf("%3u [%3u]: ", i, i);
3184
+        cli_bytetype_helper(bc, bc->globaltys[i]);
3185
+        printf(" unknown\n");
3186
+    }
3187
+    printf("------------------------------------------------------------------------\n");
3188
+
3189
+    // arguments and local values
3190
+    func = &bc->funcs[funcid];
3191
+    printf("found %d values with %d arguments and %d locals\n",
3192
+           func->numValues, func->numArgs, func->numLocals);
3193
+    printf("VID  ID    VALUE\n");
3194
+    printf("------------------------------------------------------------------------\n");
3195
+    for (i = 0; i < func->numValues; ++i) {
3196
+        printf("%3u [%3u]: ", i, total++);
3197
+        cli_bytetype_helper(bc, func->types[i]);
3198
+        if (i < func->numArgs)
3199
+            printf("argument");
3200
+        printf("\n");
3201
+    }
3202
+    printf("------------------------------------------------------------------------\n");
3203
+    
3204
+    // constants
3205
+    printf("found a total of %d constants\n", func->numConstants);
3206
+    printf("CID  ID    VALUE\n");
3207
+    printf("------------------------------------------------------------------------\n");
3208
+    for (i = 0; i < func->numConstants; ++i) {
3209
+        printf("%3u [%3u]: %llu(0x%llx)\n", i, total++, func->constants[i], func->constants[i]);
3210
+    }
3211
+    printf("------------------------------------------------------------------------\n");
3212
+    printf("found a total of %u total values\n", total);
3213
+    printf("------------------------------------------------------------------------\n");
3214
+    return;
3215
+}
3216
+
3217
+void cli_byteinst_describe(const struct cli_bc_inst *inst, unsigned *bbnum)
3218
+{
3219
+    unsigned j;
3220
+    char inst_str[256];
3221
+
3222
+    if (inst->opcode > OP_BC_INVALID) {
3223
+        printf("opcode %u[%u] of type %u is not implemented yet!",
3224
+               inst->opcode, inst->interp_op/5, inst->interp_op%5);
3225
+        return;
3226
+    }
3227
+
3228
+    snprintf(inst_str, 256, "%-20s[%-3d/%3d/%3d]", bc_opstr[inst->opcode], 
3229
+             inst->opcode, inst->interp_op, inst->interp_op%inst->opcode);
3230
+    printf("%-35s", inst_str);
3231
+    switch (inst->opcode) {
3232
+        // binary operations
3233
+    case OP_BC_ADD:
3234
+        printf("%d = %d + %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3235
+        break;
3236
+    case OP_BC_SUB:
3237
+        printf("%d = %d - %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3238
+        break;
3239
+    case OP_BC_MUL:
3240
+        printf("%d = %d * %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3241
+        break;
3242
+    case OP_BC_UDIV:
3243
+        printf("%d = %d / %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3244
+        break;
3245
+    case OP_BC_SDIV:
3246
+        printf("%d = %d / %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3247
+        break;
3248
+    case OP_BC_UREM:
3249
+        printf("%d = %d %% %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3250
+        break;
3251
+    case OP_BC_SREM:
3252
+        printf("%d = %d %% %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3253
+        break;
3254
+    case OP_BC_SHL:
3255
+        printf("%d = %d << %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3256
+        break;
3257
+    case OP_BC_LSHR:
3258
+        printf("%d = %d >> %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3259
+        break;
3260
+    case OP_BC_ASHR:
3261
+        printf("%d = %d >> %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3262
+        break;
3263
+    case OP_BC_AND:
3264
+        printf("%d = %d & %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3265
+        break;
3266
+    case OP_BC_OR:
3267
+        printf("%d = %d | %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3268
+        break;
3269
+    case OP_BC_XOR:
3270
+        printf("%d = %d ^ %d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3271
+        break;
3272
+
3273
+        // casting operations
3274
+    case OP_BC_TRUNC:
3275
+        printf("%d = %d trunc %llx", inst->dest, inst->u.cast.source, inst->u.cast.mask);
3276
+        break;
3277
+    case OP_BC_SEXT:
3278
+        printf("%d = %d sext %llx", inst->dest, inst->u.cast.source, inst->u.cast.mask);
3279
+        break;
3280
+    case OP_BC_ZEXT:
3281
+        printf("%d = %d zext %llx", inst->dest, inst->u.cast.source, inst->u.cast.mask);
3282
+        break;
3283
+        
3284
+        // control operations (termination instructions)
3285
+    case OP_BC_BRANCH:
3286
+        printf("br %d ? bb.%d : bb.%d", inst->u.branch.condition,
3287
+               inst->u.branch.br_true, inst->u.branch.br_false);
3288
+        (*bbnum)++;
3289
+        break;
3290
+    case OP_BC_JMP:
3291
+        printf("jmp bb.%d", inst->u.jump);
3292
+        (*bbnum)++;
3293
+        break;
3294
+    case OP_BC_RET:
3295
+        printf("ret %d", inst->u.unaryop);
3296
+        (*bbnum)++;
3297
+        break;
3298
+    case OP_BC_RET_VOID:
3299
+        printf("ret void");
3300
+        (*bbnum)++;
3301
+        break;
3302
+
3303
+        // comparison operations
3304
+    case OP_BC_ICMP_EQ:
3305
+        printf("%d = (%d == %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3306
+        break;
3307
+    case OP_BC_ICMP_NE:
3308
+        printf("%d = (%d != %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3309
+        break;
3310
+    case OP_BC_ICMP_UGT:
3311
+        printf("%d = (%d > %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3312
+        break;
3313
+    case OP_BC_ICMP_UGE:
3314
+        printf("%d = (%d >= %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3315
+        break;
3316
+    case OP_BC_ICMP_ULT:
3317
+        printf("%d = (%d > %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3318
+        break;
3319
+    case OP_BC_ICMP_ULE:
3320
+        printf("%d = (%d >= %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3321
+        break;
3322
+    case OP_BC_ICMP_SGT:
3323
+        printf("%d = (%d > %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3324
+        break;
3325
+    case OP_BC_ICMP_SGE:
3326
+        printf("%d = (%d >= %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3327
+        break;
3328
+    case OP_BC_ICMP_SLE:
3329
+        printf("%d = (%d <= %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3330
+        break;
3331
+    case OP_BC_ICMP_SLT:
3332
+        printf("%d = (%d < %d)", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3333
+        break;
3334
+    case OP_BC_SELECT:
3335
+        printf("%d = %d ? %d : %d)", inst->dest, inst->u.three[0], 
3336
+               inst->u.three[1], inst->u.three[2]);
3337
+        break;
3338
+
3339
+        // function calling
3340
+    case OP_BC_CALL_DIRECT:
3341
+        printf("%d = call F.%d (", inst->dest, inst->u.ops.funcid);
3342
+        for (j = 0; j < inst->u.ops.numOps; ++j) {
3343
+            if (j == inst->u.ops.numOps-1) {
3344
+                printf("%d", inst->u.ops.ops[j]);
3345
+            }
3346
+            else {
3347
+                printf("%d, ", inst->u.ops.ops[j]);
3348
+            }
3349
+        }
3350
+        printf(")");
3351
+        break;
3352
+    case OP_BC_CALL_API:
3353
+        {
3354
+            if (inst->u.ops.funcid > cli_numapicalls) {
3355
+                printf("apicall FID %d not yet implemented!\n", inst->u.ops.funcid);
3356
+                break;
3357
+            }
3358
+            const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid];
3359
+            switch (api->kind) {
3360
+            case 0:
3361
+                printf("%d = %s[%d] (%d, %d)", inst->dest, api->name,
3362
+                       inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1]);
3363
+                break;
3364
+            case 1:
3365
+                printf("%d = %s[%d] (p.%d, %d)", inst->dest, api->name,
3366
+                       inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1]);
3367
+                break;
3368
+            case 2:
3369
+                printf("%d = %s[%d] (%d)", inst->dest, api->name,
3370
+                       inst->u.ops.funcid, inst->u.ops.ops[0]);
3371
+                break;
3372
+            case 3:
3373
+                printf("p.%d = %s[%d] (%d)", inst->dest, api->name,
3374
+                       inst->u.ops.funcid, inst->u.ops.ops[0]);
3375
+                break;
3376
+            case 4:
3377
+                printf("%d = %s[%d] (p.%d, %d, %d, %d, %d)", inst->dest, api->name,
3378
+                       inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1],
3379
+                       inst->u.ops.ops[2], inst->u.ops.ops[3], inst->u.ops.ops[4]);
3380
+                break;
3381
+            case 5:
3382
+                printf("%d = %s[%d] ()", inst->dest, api->name,
3383
+                       inst->u.ops.funcid);
3384
+                break;
3385
+            case 6:
3386
+                printf("p.%d = %s[%d] (%d, %d)", inst->dest, api->name,
3387
+                       inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1]);
3388
+                break;
3389
+            case 7:
3390
+                printf("%d = %s[%d] (%d, %d, %d)", inst->dest, api->name,
3391
+                       inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1],
3392
+                       inst->u.ops.ops[2]);
3393
+                break;
3394
+            case 8:
3395
+                printf("%d = %s[%d] (p.%d, %d, p.%d, %d)", inst->dest, api->name,
3396
+                       inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1],
3397
+                       inst->u.ops.ops[2], inst->u.ops.ops[3]);
3398
+                break;
3399
+            case 9:
3400
+                printf("%d = %s[%d] (p.%d, %d, %d)", inst->dest, api->name,
3401
+                       inst->u.ops.funcid, inst->u.ops.ops[0], inst->u.ops.ops[1],
3402
+                       inst->u.ops.ops[2]);
3403
+                break;
3404
+            default:
3405
+                printf("type %u apicalls not yet implemented!\n", api->kind);
3406
+                break;
3407
+            }
3408
+        }
3409
+        break;
3410
+
3411
+        // memory operations
3412
+    case OP_BC_COPY:
3413
+        printf("cp %d -> %d", inst->u.binop[0], inst->u.binop[1]);
3414
+        break;
3415
+    case OP_BC_GEP1:
3416
+        printf("%d = gep1 p.%d + (%d * %d)", inst->dest, inst->u.three[1],
3417
+               inst->u.three[2], inst->u.three[0]);
3418
+        break;
3419
+    case OP_BC_GEPZ:
3420
+        printf("%d = gepz p.%d + (%d)", inst->dest, 
3421
+               inst->u.three[1], inst->u.three[2]);
3422
+        break;
3423
+    case OP_BC_GEPN:
3424
+        printf("illegal opcode, impossible");
3425
+        break;
3426
+    case OP_BC_STORE:
3427
+        printf("store %d -> p.%d", inst->u.binop[0], inst->u.binop[1]);
3428
+        break;
3429
+    case OP_BC_LOAD:
3430
+        printf("load  %d <- p.%d", inst->dest, inst->u.unaryop);
3431
+        break;
3432
+
3433
+        // llvm instrinsics
3434
+    case OP_BC_MEMSET:
3435
+        printf("%d = memset (p.%d, %d, %d)", inst->dest, inst->u.three[0],
3436
+               inst->u.three[1], inst->u.three[2]);
3437
+        break;
3438
+    case OP_BC_MEMCPY:
3439
+        printf("%d = memcpy (p.%d, p.%d, %d)", inst->dest, inst->u.three[0],
3440
+               inst->u.three[1], inst->u.three[2]);
3441
+        break;
3442
+    case OP_BC_MEMMOVE:
3443
+        printf("%d = memmove (p.%d, p.%d, %d)", inst->dest, inst->u.three[0],
3444
+               inst->u.three[1], inst->u.three[2]);
3445
+        break;
3446
+    case OP_BC_MEMCMP:
3447
+        printf("%d = memcmp (p.%d, p.%d, %d)", inst->dest, inst->u.three[0],
3448
+               inst->u.three[1], inst->u.three[2]);
3449
+        break;
3450
+
3451
+        // utility operations
3452
+    case OP_BC_ISBIGENDIAN:
3453
+        printf("%d = isbigendian()", inst->dest);
3454
+        break;
3455
+    case OP_BC_ABORT:
3456
+        printf("ABORT!!");
3457
+        break;
3458
+    case OP_BC_BSWAP16:
3459
+        printf("%d = bswap16 %d", inst->dest, inst->u.unaryop);
3460
+        break;
3461
+    case OP_BC_BSWAP32:
3462
+        printf("%d = bswap32 %d", inst->dest, inst->u.unaryop);
3463
+        break;
3464
+    case OP_BC_BSWAP64:
3465
+        printf("%d = bswap64 %d", inst->dest, inst->u.unaryop);
3466
+        break;
3467
+    case OP_BC_PTRDIFF32:
3468
+        printf("%d = ptrdiff32 p.%d p.%d", inst->dest, inst->u.binop[0], inst->u.binop[1]);
3469
+        break;
3470
+    case OP_BC_PTRTOINT64:
3471
+        printf("%d = ptrtoint64 p.%d", inst->dest, inst->u.unaryop);
3472
+        break;
3473
+    case OP_BC_INVALID:  /* last */
3474
+        printf("INVALID!!");
3475
+        break;
3476
+
3477
+    default:
3478
+        // redundant check
3479
+        printf("opcode %u[%u] of type %u is not implemented yet!",
3480
+               inst->opcode, inst->interp_op/5, inst->interp_op%5);
3481
+        break;
3482
+    }
3483
+}
3484
+
3485
+void cli_bytefunc_describe(const struct cli_bc *bc, unsigned funcid)
3486
+{
3487
+    unsigned i, bbnum, bbpre;
3488
+    const struct cli_bc_func *func;
3489
+
3490
+    if (funcid >= bc->num_func) {
3491
+        printf("bytecode diagnostic: funcid [%u] outside byecode numfuncs [%u]\n",
3492
+               funcid, bc->num_func);
3493
+        return;
3494
+    }
3495
+
3496
+    func = &bc->funcs[funcid];
3497
+
3498
+    printf("FUNCTION ID: F.%d -> NUMINSTS %d\n", funcid, func->numInsts);
3499
+    printf("BB   IDX  OPCODE              [ID /IID/MOD]  INST\n");
3500
+    printf("------------------------------------------------------------------------\n");
3501
+    bbpre = 0; bbnum = 0;
3502
+    for (i = 0; i < func->numInsts; ++i) {
3503
+        if (bbpre != bbnum) {
3504
+            printf("\n");
3505
+            bbpre = bbnum;
3506
+        }
3507
+
3508
+        printf("%3d  %3d  ", bbnum, i);
3509
+        cli_byteinst_describe(&func->allinsts[i], &bbnum);
3510
+        printf("\n");
3511
+    }
3512
+    printf("------------------------------------------------------------------------\n");
3513
+}
... ...
@@ -114,7 +114,14 @@ int cli_bytecode_prepare2(struct cl_engine *engine, struct cli_all_bc *allbc, un
114 114
 int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, struct cli_bc_ctx *ctx);
115 115
 void cli_bytecode_destroy(struct cli_bc *bc);
116 116
 int cli_bytecode_done(struct cli_all_bc *allbc);
117
+
118
+/* Bytecode IR descriptions */
117 119
 void cli_bytecode_describe(const struct cli_bc *bc);
120
+void cli_bytetype_describe(const struct cli_bc *bc);
121
+void cli_bytevalue_describe(const struct cli_bc *bc, unsigned funcid);
122
+void cli_byteinst_describe(const struct cli_bc_inst *inst, unsigned *bbnum);
123
+void cli_bytefunc_describe(const struct cli_bc *bc, unsigned funcid);
124
+
118 125
 
119 126
 /* Hooks */
120 127
 struct cli_exe_info;
... ...
@@ -214,8 +214,8 @@ const struct cli_bc_type cli_apicall_types[]={
214 214
 	{DArrayType, cli_tmp29, 3, 0, 0},
215 215
 	{DArrayType, cli_tmp30, 10, 0, 0}
216 216
 };
217
-
218 217
 const unsigned cli_apicall_maxtypes=sizeof(cli_apicall_types)/sizeof(cli_apicall_types[0]);
218
+
219 219
 const struct cli_apicall cli_apicalls[]={
220 220
 /* Bytecode APIcalls BEGIN */
221 221
 	{"test1", 10, 0, 0},
... ...
@@ -320,6 +320,8 @@ const struct cli_apicall cli_apicalls[]={
320 320
 	{"json_get_int", 8, 33, 2}
321 321
 /* Bytecode APIcalls END */
322 322
 };
323
+const unsigned cli_numapicalls=sizeof(cli_apicalls)/sizeof(cli_apicalls[0]);
324
+
323 325
 const cli_apicall_int2 cli_apicalls0[] = {
324 326
 	(cli_apicall_int2)cli_bcapi_test1,
325 327
 	(cli_apicall_int2)cli_bcapi_seek,
... ...
@@ -199,6 +199,10 @@ CLAMAV_PRIVATE {
199 199
     cli_bytecode_debug_printsrc;
200 200
     cli_bytecode_printversion;
201 201
     cli_bytecode_describe;
202
+    cli_bytetype_describe;
203
+    cli_bytevalue_describe;
204
+    cli_byteinst_describe;
205
+    cli_bytefunc_describe;
202 206
     cli_printcxxver;
203 207
     cli_detect_environment;
204 208
     cli_disasm_one;
... ...
@@ -141,6 +141,7 @@ const struct clam_option __clam_options[] = {
141 141
     { NULL, "trust-bytecode", 't', CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMBC, "Trust loaded bytecode (default yes)", ""},
142 142
     { NULL, "info", 'i', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Load and print bytecode information without executing", ""},
143 143
     { NULL, "printsrc", 'p', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Print source code of bytecode", ""},
144
+    { NULL, "printbcir", 'c', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Print bytecode representation of bytecode signature", ""},
144 145
     { NULL, "input", 'r', CLOPT_TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMBC, "Input file to run the bytecode n", ""},
145 146
     { NULL, "trace", 't', CLOPT_TYPE_NUMBER, MATCH_NUMBER, 7, NULL, 0, OPT_CLAMBC, "bytecode trace level",""},
146 147
     { NULL, "no-trace-showsource", 's', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMBC, "Don't show source line during tracing",""},