int convert_iinc(struct parse_context *ctx) { struct statement *store_stmt; struct expression *local_expression, *binop_expression, *const_expression; unsigned int index; int const_value; store_stmt = alloc_statement(STMT_STORE); if (!store_stmt) goto failed; if (ctx->is_wide) { index = bytecode_read_u16(ctx->buffer); const_value = bytecode_read_s16(ctx->buffer); } else { index = bytecode_read_u8(ctx->buffer); const_value = bytecode_read_s8(ctx->buffer); } local_expression = local_expr(J_INT, index); if (!local_expression) goto failed; store_stmt->store_dest = &local_expression->node; const_expression = value_expr(J_INT, const_value); if (!const_expression) goto failed; expr_get(local_expression); binop_expression = binop_expr(J_INT, OP_ADD, local_expression, const_expression); if (!binop_expression) { expr_put(local_expression); expr_put(const_expression); goto failed; } store_stmt->store_src = &binop_expression->node; convert_statement(ctx, store_stmt); return 0; failed: free_statement(store_stmt); return warn("out of memory"), -ENOMEM; }
static int convert_if_cmp(struct parse_context *ctx, enum vm_type vm_type, enum binary_operator binop) { struct statement *stmt; struct expression *if_value1, *if_value2; if_value2 = stack_pop(ctx->bb->mimic_stack); if_value1 = stack_pop(ctx->bb->mimic_stack); stmt = __convert_if(ctx, vm_type, binop, if_value1, if_value2); if (!stmt) return -ENOMEM; convert_statement(ctx, stmt); return 0; }
struct expression * dup_expr(struct parse_context *ctx, struct expression *expr) { struct expression *dest; struct statement *stmt; dest = temporary_expr(expr->vm_type, ctx->cu); expr_get(dest); stmt = alloc_statement(STMT_STORE); stmt->store_dest = &dest->node; stmt->store_src = &expr->node; convert_statement(ctx, stmt); return dest; }
static int convert_if(struct parse_context *ctx, enum binary_operator binop) { struct statement *stmt; struct expression *if_value, *zero_value; zero_value = value_expr(J_INT, 0); if (!zero_value) return -ENOMEM; if_value = stack_pop(ctx->bb->mimic_stack); stmt = __convert_if(ctx, J_INT, binop, if_value, zero_value); if (!stmt) { expr_put(zero_value); return -ENOMEM; } convert_statement(ctx, stmt); return 0; }
int convert_goto(struct parse_context *ctx) { struct basic_block *target_bb; struct statement *goto_stmt; int32_t goto_target; goto_target = bytecode_read_branch_target(ctx->opc, ctx->buffer); target_bb = find_bb(ctx->cu, goto_target + ctx->offset); goto_stmt = alloc_statement(STMT_GOTO); if (!goto_stmt) return -ENOMEM; goto_stmt->goto_target = target_bb; convert_statement(ctx, goto_stmt); return 0; }
int convert_athrow(struct parse_context *ctx) { struct stack *mimic_stack = ctx->bb->mimic_stack; struct expression *exception_ref; struct expression *nullcheck; struct statement *stmt; stmt = alloc_statement(STMT_ATHROW); if (!stmt) return -ENOMEM; exception_ref = stack_pop(mimic_stack); nullcheck = null_check_expr(exception_ref); if (!nullcheck) return -ENOMEM; stmt->exception_ref = &nullcheck->node; /* * According to the JVM specification athrow operation is * supposed to discard the java stack and push exception * reference on it. We don't do the latter because exception * reference is not transferred to exception handlers in * BC2IR layer. */ while (!stack_is_empty(mimic_stack)) { struct expression *expr = stack_pop(mimic_stack); expr_put(expr); } convert_statement(ctx, stmt); return 0; }
int convert_lookupswitch(struct parse_context *ctx) { struct lookupswitch_info info; struct lookupswitch *table; struct basic_block *master_bb; struct basic_block *default_bb; struct basic_block *b1; get_lookupswitch_info(ctx->code, ctx->offset, &info); ctx->buffer->pos += info.insn_size; default_bb = find_bb(ctx->cu, ctx->offset + info.default_target); if (!default_bb) goto fail_default_bb; master_bb = ctx->bb; b1 = bb_split(master_bb, master_bb->end); assert(b1); b1->has_branch = true; bb_add_successor(master_bb, default_bb ); bb_add_successor(master_bb, b1); for (unsigned int i = 0; i < info.count; i++) { struct basic_block *target_bb; int32_t target; target = read_lookupswitch_target(&info, i); target_bb = find_bb(ctx->cu, ctx->offset + target); if (!bb_successors_contains(b1, target_bb)) bb_add_successor(b1, target_bb); } table = alloc_lookupswitch(&info, ctx->cu, b1, ctx->offset); if (!table) return -ENOMEM; struct statement *if_null_stmt; struct statement *stmt; struct expression *key; struct expression *bsearch; struct expression *pure_bsearch; key = stack_pop(ctx->bb->mimic_stack); bsearch = lookupswitch_bsearch_expr(key, table); if (!bsearch) return -1; pure_bsearch = get_pure_expr(ctx, bsearch); if_null_stmt = branch_if_null_stmt(default_bb, pure_bsearch); if (!if_null_stmt) goto fail_null_stmt; stmt = alloc_statement(STMT_LOOKUPSWITCH_JUMP); if (!stmt) goto fail_stmt; expr_get(pure_bsearch); stmt->lookupswitch_target = &pure_bsearch->node; convert_statement(ctx, if_null_stmt); do_convert_statement(b1, stmt, ctx->offset); return 0; fail_stmt: free_statement(if_null_stmt); fail_null_stmt: free_lookupswitch(table); fail_default_bb: return -1; }