static void assert_dup_x2_stack(unsigned char opc, struct expression *value1, struct expression *value2, struct expression *value3) { struct basic_block *bb; struct statement *stmt; bb = alloc_simple_bb(&opc, 1); stack_push(bb->mimic_stack, expr_get(value3)); stack_push(bb->mimic_stack, expr_get(value2)); stack_push(bb->mimic_stack, expr_get(value1)); convert_to_ir(bb->b_parent); stmt = stmt_entry(bb->stmt_list.next); assert_store_stmt(stmt); assert_ptr_equals(value1, to_expr(stmt->store_src)); assert_temporary_expr(value1->vm_type, stmt->store_dest); assert_ptr_equals(to_expr(stmt->store_dest), pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value2, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value3, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value1, pop_and_put_expr(bb->mimic_stack)); assert_true(stack_is_empty(bb->mimic_stack)); free_simple_bb(bb); }
static void __assert_convert_load(unsigned char *code, unsigned long code_size, enum vm_type expected_type, unsigned char expected_index) { struct expression *expr; struct statement *stmt; struct basic_block *bb; bb = alloc_simple_bb(code, code_size); convert_to_ir(bb->b_parent); expr = stack_pop(bb->mimic_stack); assert_temporary_expr(expected_type, &expr->node); stmt = stmt_entry(bb->stmt_list.next); assert_store_stmt(stmt); assert_local_expr(expected_type, expected_index, stmt->store_src); assert_ptr_equals(&expr->node, stmt->store_dest); assert_true(stack_is_empty(bb->mimic_stack)); expr_put(expr); free_simple_bb(bb); }
void test_convert_tableswitch_bbs1(void) { struct basic_block *bb0, *bb1, *bb2, *bb3, *bb4, *bb5, *bb6; struct compilation_unit *cu; struct cafebabe_method_info method_info; struct vm_method method = { .code_attribute.code = tableswitch1, .code_attribute.code_length = ARRAY_SIZE(tableswitch1), .method = &method_info, }; memset(&method_info, 0, sizeof(method_info)); cu = compilation_unit_alloc(&method); analyze_control_flow(cu); convert_to_ir(cu); assert_int_equals(7, nr_bblocks(cu)); bb0 = bb_entry(cu->bb_list.next); bb1 = bb_entry(bb0->bb_list_node.next); bb2 = bb_entry(bb1->bb_list_node.next); bb3 = bb_entry(bb2->bb_list_node.next); bb4 = bb_entry(bb3->bb_list_node.next); bb5 = bb_entry(bb4->bb_list_node.next); bb6 = bb_entry(bb5->bb_list_node.next); assert_basic_block_successors((struct basic_block*[]){bb6, bb1}, 2, bb0); assert_basic_block_successors((struct basic_block*[]){bb6, bb2}, 2, bb1);
static void assert_dup2_x2_stack(unsigned char opc, struct expression *value1, struct expression *value2, struct expression *value3, struct expression *value4) { struct statement *stmt, *stmt2; struct basic_block *bb; if (value1->vm_type == J_LONG || value1->vm_type == J_DOUBLE) { if (value2->vm_type == J_LONG || value2->vm_type == J_DOUBLE) { assert_dup_x1_stack(opc, value1, value2); return; } else { assert_dup_x2_stack(opc, value1, value2, value3); return; } } else { if (value3->vm_type == J_LONG || value3->vm_type == J_DOUBLE) { assert_dup2_x1_stack(opc, value1, value2, value3); return; } } bb = alloc_simple_bb(&opc, 1); stack_push(bb->mimic_stack, expr_get(value4)); stack_push(bb->mimic_stack, expr_get(value3)); stack_push(bb->mimic_stack, expr_get(value2)); stack_push(bb->mimic_stack, expr_get(value1)); convert_to_ir(bb->b_parent); stmt = stmt_entry(bb->stmt_list.next); stmt2 = stmt_entry(stmt->stmt_list_node.next); assert_store_stmt(stmt); assert_ptr_equals(value2, to_expr(stmt->store_src)); assert_temporary_expr(value2->vm_type, stmt->store_dest); assert_store_stmt(stmt2); assert_ptr_equals(value1, to_expr(stmt2->store_src)); assert_temporary_expr(value1->vm_type, stmt2->store_dest); assert_ptr_equals(to_expr(stmt2->store_dest), pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(to_expr(stmt->store_dest), pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value3, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value4, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value1, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value2, pop_and_put_expr(bb->mimic_stack)); assert_true(stack_is_empty(bb->mimic_stack)); free_simple_bb(bb); }
static void assert_convert_fconst(enum vm_type expected_type, double expected_value, unsigned char opc) { struct expression *expr; struct basic_block *bb; bb = alloc_simple_bb(&opc, 1); convert_to_ir(bb->b_parent); expr = stack_pop(bb->mimic_stack); assert_fvalue_expr(expected_type, expected_value, &expr->node); assert_true(stack_is_empty(bb->mimic_stack)); expr_put(expr); free_simple_bb(bb); }
static void assert_swap_stack(unsigned char opc, void *value1, void *value2) { struct basic_block *bb; bb = alloc_simple_bb(&opc, 1); stack_push(bb->mimic_stack, expr_get(value1)); stack_push(bb->mimic_stack, expr_get(value2)); convert_to_ir(bb->b_parent); assert_ptr_equals(value1, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value2, pop_and_put_expr(bb->mimic_stack)); assert_true(stack_is_empty(bb->mimic_stack)); free_simple_bb(bb); }
static void __assert_convert_const(enum vm_type expected_type, long long expected_value, unsigned char *code, unsigned long code_size) { struct expression *expr; struct basic_block *bb; bb = alloc_simple_bb(code, code_size); convert_to_ir(bb->b_parent); expr = stack_pop(bb->mimic_stack); assert_value_expr(expected_type, expected_value, &expr->node); assert_true(stack_is_empty(bb->mimic_stack)); expr_put(expr); free_simple_bb(bb); }
int compile(struct compilation_unit *cu) { int err; if (opt_trace_method) trace_method(cu); err = analyze_control_flow(cu); if (err) goto out; err = convert_to_ir(cu); if (err) goto out; err = sort_basic_blocks(cu); if (err) goto out; if (opt_trace_cfg) trace_cfg(cu); if (opt_trace_tree_ir) trace_tree_ir(cu); err = select_instructions(cu); if (err) goto out; compute_insn_positions(cu); if (opt_trace_lir) trace_lir(cu); err = analyze_liveness(cu); if (err) goto out; if (opt_trace_liveness) trace_liveness(cu); err = allocate_registers(cu); if (err) goto out; if (opt_trace_regalloc) trace_regalloc(cu); err = insert_spill_reload_insns(cu); if (err) goto out; assert(all_insn_have_bytecode_offset(cu)); err = emit_machine_code(cu); if (err) goto out; if (opt_trace_machine_code) trace_machine_code(cu); cu->is_compiled = true; perf_append_cu(cu); out: if (err) compile_error(cu, err); return err; }
static int do_compile(struct compilation_unit *cu) { bool ssa_enable; int err; if (opt_print_compilation) print_compilation(cu->method); if (opt_trace_compile) trace_method(cu); err = inline_subroutines(cu->method); if (err) goto out; if (opt_trace_bytecode) trace_bytecode(cu->method); err = analyze_control_flow(cu); if (err) goto out; err = convert_to_ir(cu); if (err) goto out; ssa_enable = opt_ssa_enable && uses_array_ops(cu); if (ssa_enable) { err = compute_dfns(cu); if (err) goto out; } if (opt_trace_cfg) trace_cfg(cu); if (opt_trace_tree_ir) trace_tree_ir(cu); err = select_instructions(cu); if (err) goto out; compute_insn_positions(cu); if (opt_trace_lir) trace_lir(cu); if (ssa_enable) { err = compute_dom(cu); if (err) goto out; err = compute_dom_frontier(cu); if (err) goto out; err = lir_to_ssa(cu); if (err) goto out; if(opt_trace_ssa) trace_ssa(cu); imm_copy_propagation(cu); abc_removal(cu); err = dce(cu); if (err) goto out; err = ssa_to_lir(cu); if (err) goto out; } err = analyze_liveness(cu); if (err) goto out; if (opt_trace_liveness) trace_liveness(cu); err = allocate_registers(cu); if (err) goto out; err = mark_clobbers(cu); if (err) goto out; err = insert_spill_reload_insns(cu); if (err) goto out; if (opt_trace_regalloc) trace_regalloc(cu); err = convert_ic_calls(cu); if (err) goto out; assert(all_insn_have_bytecode_offset(cu)); err = peephole_optimize(cu); if (err) goto out; err = emit_machine_code(cu); if (err) goto out; err = build_bc_offset_map(cu); if (err) goto out; if (opt_trace_machine_code) trace_machine_code(cu); resolve_fixup_offsets(cu); perf_append_cu(cu); out: if (opt_trace_compile) trace_flush(); if (err && !exception_occurred()) compile_error(cu, err); return err; }