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;
}
Exemple #2
0
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;
}
Exemple #3
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;
}
Exemple #4
0
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;
}
Exemple #5
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;
}
Exemple #6
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;
}
Exemple #7
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;
}