static void assert_emits_branch_target(unsigned char expected_prefix, unsigned char expected_opc, unsigned char expected_target_1, unsigned char expected_target_2, unsigned char expected_target_3, unsigned char expected_target_4, struct basic_block *target_bb, enum insn_type insn_type) { struct basic_block *branch_bb; struct buffer *buf; struct insn *insn; insn = branch_insn(insn_type, target_bb); branch_bb = alloc_basic_block(NULL, 1, 2); buf = alloc_buffer(); emit_body(target_bb, buf); bb_add_insn(branch_bb, insn); emit_body(branch_bb, buf); if (expected_prefix) expected_target_1--; assert_prefixed_mem_insn_5(expected_prefix, expected_opc, expected_target_1, expected_target_2, expected_target_3, expected_target_4, buffer_ptr(buf) + insn->mach_offset); free_basic_block(branch_bb); free_buffer(buf); }
static void assert_forward_branch(unsigned char expected_prefix, unsigned char expected_opc, enum insn_type insn_type) { struct basic_block *bb; bb = alloc_basic_block(NULL, 0, 1); assert_emit_prefixed_insn_5(expected_prefix, expected_opc, 0x00, 0x00, 0x00, 0x00, branch_insn(insn_type, bb)); free_basic_block(bb); }
void test_branch_does_not_define_or_use_anything(void) { struct basic_block bb; assert_does_not_define_or_use_anything(branch_insn(INSN_JE_BRANCH, &bb)); assert_does_not_define_or_use_anything(branch_insn(INSN_JGE_BRANCH, &bb)); assert_does_not_define_or_use_anything(branch_insn(INSN_JG_BRANCH, &bb)); assert_does_not_define_or_use_anything(branch_insn(INSN_JLE_BRANCH, &bb)); assert_does_not_define_or_use_anything(branch_insn(INSN_JL_BRANCH, &bb)); assert_does_not_define_or_use_anything(branch_insn(INSN_JMP_BRANCH, &bb)); assert_does_not_define_or_use_anything(branch_insn(INSN_JNE_BRANCH, &bb)); }
void test_variable_range_spans_two_basic_blocks(void) { struct basic_block *bb1, *bb2; struct compilation_unit *cu; struct var_info *r1, *r2; struct insn *insn[4]; cu = compilation_unit_alloc(&method); r1 = get_var(cu); r2 = get_var(cu); bb1 = get_basic_block(cu, 0, 2); bb2 = get_basic_block(cu, 2, 4); bb_add_successor(bb1, bb2); insn[2] = imm_insn(INSN_SETL, 0x02, r2); bb_add_insn(bb2, insn[2]); insn[3] = arithmetic_insn(INSN_ADD, r1, r2, r2); bb_add_insn(bb2, insn[3]); insn[0] = imm_insn(INSN_SETL, 0x01, r1); bb_add_insn(bb1, insn[0]); insn[1] = branch_insn(INSN_JMP, bb2); bb_add_insn(bb1, insn[1]); compute_insn_positions(cu); analyze_liveness(cu); assert_defines(bb1, r1); assert_defines(bb2, r2); assert_uses(bb2, r1); assert_live_range(r1->interval, 0, 4); assert_live_range(r2->interval, 2, 4); assert_ptr_equals(insn[0], r1->interval->insn_array[0]); assert_ptr_equals(insn[1], r1->interval->insn_array[1]); assert_ptr_equals(insn[2], r1->interval->insn_array[2]); assert_ptr_equals(insn[3], r1->interval->insn_array[3]); assert_ptr_equals(insn[2], r2->interval->insn_array[0]); assert_ptr_equals(insn[3], r2->interval->insn_array[1]); free_compilation_unit(cu); }
static void assert_adds_self_to_unresolved_list_for_forward_branches( unsigned char expected_prefix, unsigned char expected_opc, enum insn_type insn_type) { struct basic_block *if_true; struct insn *insn; if_true = alloc_basic_block(NULL, 0, 1); insn = branch_insn(insn_type, if_true); assert_emit_prefixed_insn_5(expected_prefix, expected_opc, 0x00, 0x00, 0x00, 0x00, insn); assert_ptr_equals(insn, list_entry(if_true->backpatch_insns.next, struct insn, branch_list_node)); free_basic_block(if_true); }
static void assert_backpatches_unresolved_branches_when_emitting_target( unsigned char expected_prefix, unsigned char expected_opc, enum insn_type insn_type) { struct basic_block *target_bb, *branch_bb; struct compilation_unit *cu; struct var_info *eax; cu = compilation_unit_alloc(&method); eax = get_fixed_var(cu, MACH_REG_EAX); branch_bb = get_basic_block(cu, 0, 1); target_bb = get_basic_block(cu, 1, 2); bb_add_insn(branch_bb, branch_insn(insn_type, target_bb)); assert_backpatches_branches(expected_prefix, expected_opc, 0x00, branch_bb, target_bb); bb_add_insn(branch_bb, imm_reg_insn(INSN_ADD_IMM_REG, 0x01, eax)); assert_backpatches_branches(expected_prefix, expected_opc, 0x03, branch_bb, target_bb); free_compilation_unit(cu); }
int main(int argc, char **argv) { int i; double x; /* results of /bin/ls with mica v02 */ /* TODO - read this from a file */ total=994400; counts[MEM_READ]=379835; counts[MEM_WRITE]=182969; counts[BRANCH]=195902; // counts[INTEGER]=706400; counts[INTEGER]=145734; counts[FP]=0; counts[STACK]=39869; counts[SHIFT]=13528; counts[STRING]=648; counts[SSE]=0; counts[OTHER]=35915; make_ratios(); for(i=0;i<TOTAL;i++) { fprintf(stderr,"%i %f %f\n",i,ratios[i],ranges[i]); } printf("\t.globl _start\n"); printf("_start:\n"); for(i=0;i<total;i++) { x=drand48(); if (x<ranges[MEM_READ]) mem_read_insn(); else if (x<ranges[MEM_WRITE]) mem_write_insn(); else if (x<ranges[BRANCH]) branch_insn(); else if (x<ranges[INTEGER]) integer_insn(); else if (x<ranges[FP]) fp_insn(); else if (x<ranges[STACK]) stack_insn(); else if (x<ranges[SHIFT]) shift_insn(); else if (x<ranges[STRING]) string_insn(); else if (x<ranges[SSE]) sse_insn(); else other_insn(); } printf("\t#================================\n"); printf("\t# Exit\n"); printf("\t#================================\n"); printf("exit:\n"); printf("\txor %%ebx,%%ebx\n"); printf("\txor %%eax,%%eax\n"); printf("\tinc %%eax\t\t\t# put exit syscall number (1) in eax\n"); printf("\tint $0x80\t\t\t# and exit\n"); printf("\n"); /* data segment */ printf(".data\n"); printf("data_begin: .byte "); for(i=0;i<data_size;i++) { printf("0"); if (i!=data_size-1) { printf(","); } else { printf("\n"); } } /* bss segment */ printf(".bss\n"); printf(".lcomm bss_begin,%d\n",bss_size); return 0; }