-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | jit/jit-insn.c | 144 | ||||
-rw-r--r-- | jit/jit-rules-x86.c | 108 | ||||
-rw-r--r-- | jit/jit-rules-x86.sel | 84 | ||||
-rw-r--r-- | jit/jit-rules.h | 1 | ||||
-rw-r--r-- | tools/gen-sel-parser.y | 4 |
@@ -1,4 +1,10 @@ +2004年05月26日 Rhys Weatherley <rweather@southern-storm.com.au> + + * jit/jit-insn.c, jit/jit-rules-x86.c, jit/jit-rules-x86.sel, + jit/jit-rules.h, tools/gen-sel-parser.y: fix some compile issues + in the x86 native back end. + 2004年05月25日 Rhys Weatherley <rweather@southern-storm.com.au> * tools/.cvsignore, tools/Makefile.am, tools/gen-sel-parser.y, diff --git a/jit/jit-insn.c b/jit/jit-insn.c index 5ad7c0a..bbd18fa 100644 --- a/jit/jit-insn.c +++ b/jit/jit-insn.c @@ -4628,12 +4628,8 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags) { #if !defined(JIT_BACKEND_INTERP) jit_type_t type; - jit_value_t eh_frame_info; - jit_block_t block; jit_value_t args[2]; jit_insn_t insn; - jit_type_t params[2]; - jit_value_t struct_return; /* If "tail" is set, then we need to pop the "setjmp" context */ if((flags & JIT_CALL_TAIL) != 0 && func->has_try) @@ -4660,62 +4656,67 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags) func->builder->may_throw = 1; #if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0 - /* Get the value that holds the exception frame information */ - if((eh_frame_info = func->builder->eh_frame_info) == 0) { - type = jit_type_create_struct(0, 0, 0); - if(!type) + jit_value_t eh_frame_info; + jit_type_t params[2]; + + /* Get the value that holds the exception frame information */ + if((eh_frame_info = func->builder->eh_frame_info) == 0) + { + type = jit_type_create_struct(0, 0, 0); + if(!type) + { + return 0; + } + jit_type_set_size_and_alignment + (type, sizeof(struct jit_backtrace), sizeof(void *)); + eh_frame_info = jit_value_create(func, type); + jit_type_free(type); + if(!eh_frame_info) + { + return 0; + } + func->builder->eh_frame_info = eh_frame_info; + } + + /* Output an instruction to load the "pc" into a value */ + args[1] = jit_value_create(func, jit_type_void_ptr); + if(!(args[1])) { return 0; } - jit_type_set_size_and_alignment - (type, sizeof(struct jit_backtrace), sizeof(void *)); - eh_frame_info = jit_value_create(func, type); - jit_type_free(type); - if(!eh_frame_info) + insn = _jit_block_add_insn(func->builder->current_block); + if(!insn) { return 0; } - func->builder->eh_frame_info = eh_frame_info; - } + jit_value_ref(func, args[1]); + insn->opcode = JIT_OP_LOAD_PC; + insn->dest = args[1]; - /* Output an instruction to load the "pc" into a value */ - args[1] = jit_value_create(func, jit_type_void_ptr); - if(!(args[1])) - { - return 0; - } - insn = _jit_block_add_insn(func->builder->current_block); - if(!insn) - { - return 0; - } - jit_value_ref(func, args[1]); - insn->opcode = JIT_OP_LOAD_PC; - insn->dest = args[1]; + /* Load the address of "eh_frame_info" into another value */ + args[0] = jit_insn_address_of(func, eh_frame_info); + if(!(args[0])) + { + return 0; + } - /* Load the address of "eh_frame_info" into another value */ - args[0] = jit_insn_address_of(func, eh_frame_info); - if(!(args[0])) - { - return 0; - } + /* Create a signature for the prototype "void (void *, void *)" */ + params[0] = jit_type_void_ptr; + params[1] = jit_type_void_ptr; + type = jit_type_create_signature + (jit_abi_cdecl, jit_type_void, params, 2, 1); + if(!type) + { + return 0; + } - /* Create a signature for the prototype "void (void *, void *)" */ - params[0] = jit_type_void_ptr; - params[1] = jit_type_void_ptr; - type = jit_type_create_signature - (jit_abi_cdecl, jit_type_void, params, 2, 1); - if(!type) - { - return 0; + /* Call the "_jit_backtrace_push" function */ + jit_insn_call_native + (func, "_jit_backtrace_push", + (void *)_jit_backtrace_push, type, args, 2, JIT_CALL_NOTHROW); + jit_type_free(type); } - - /* Call the "_jit_backtrace_push" function */ - jit_insn_call_native - (func, "_jit_backtrace_push", - (void *)_jit_backtrace_push, type, args, 2, JIT_CALL_NOTHROW); - jit_type_free(type); #endif /* Update the "catch_pc" value to reflect the current context */ @@ -4735,7 +4736,7 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags) insn->opcode = JIT_OP_LOAD_PC; insn->dest = args[0]; if(!jit_insn_store_relative - (func, jit_insn_address_of(func->builder->setjmp_value), + (func, jit_insn_address_of(func, func->builder->setjmp_value), jit_jmp_catch_pc_offset, args[0])) { return 0; @@ -4760,10 +4761,7 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags) static int restore_eh_frame_after_call(jit_function_t func, int flags) { #if !defined(JIT_BACKEND_INTERP) - jit_type_t type; - jit_value_t struct_return; - jit_block_t block; - jit_insn_t insn; + jit_value_t value; /* If the "nothrow", "noreturn", or "tail" flags are set, then we don't need to worry about this */ @@ -4773,32 +4771,36 @@ static int restore_eh_frame_after_call(jit_function_t func, int flags) } #if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0 - /* Create the signature prototype "void (void)" */ - type = jit_type_create_signature - (jit_abi_cdecl, jit_type_void, 0, 0, 0); - if(!type) { - return 0; - } + jit_type_t type; - /* Call the "_jit_backtrace_pop" function */ - jit_insn_call_native - (func, "_jit_backtrace_pop", - (void *)_jit_backtrace_pop, type, 0, 0, JIT_CALL_NOTHROW); - jit_type_free(type); + /* Create the signature prototype "void (void)" */ + type = jit_type_create_signature + (jit_abi_cdecl, jit_type_void, 0, 0, 0); + if(!type) + { + return 0; + } + + /* Call the "_jit_backtrace_pop" function */ + jit_insn_call_native + (func, "_jit_backtrace_pop", + (void *)_jit_backtrace_pop, type, 0, 0, JIT_CALL_NOTHROW); + jit_type_free(type); + } #endif /* Clear the "catch_pc" value for the current context */ if(func->builder->setjmp_value != 0) { - args[0] = jit_value_create_nint_constant(func, jit_type_void_ptr, 0); - if(!(args[0])) + value = jit_value_create_nint_constant(func, jit_type_void_ptr, 0); + if(!value) { return 0; } if(!jit_insn_store_relative - (func, jit_insn_address_of(func->builder->setjmp_value), - jit_jmp_catch_pc_offset, args[0])) + (func, jit_insn_address_of(func, func->builder->setjmp_value), + jit_jmp_catch_pc_offset, value)) { return 0; } @@ -6365,14 +6367,14 @@ static int initialize_setjmp_block(jit_function_t func) /* Clear the original "catch_pc" value within "setjmp_value" */ if(!jit_insn_store_relative (func, jit_insn_address_of(func, func->builder->setjmp_value), - jit_jmp_catcher_offset, jit_value_create_nint_constant + jit_jmp_catch_pc_offset, jit_value_create_nint_constant (func, jit_type_void_ptr, 0))) { return 0; } /* Jump to this function's exception catcher */ - if(!jit_insn_branch(func, &(func->builder->catcher_label)) + if(!jit_insn_branch(func, &(func->builder->catcher_label))) { return 0; } diff --git a/jit/jit-rules-x86.c b/jit/jit-rules-x86.c index 8974bb2..c1c93d9 100644 --- a/jit/jit-rules-x86.c +++ b/jit/jit-rules-x86.c @@ -720,6 +720,8 @@ void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) int num_regs, reg; unsigned char *inst; int struct_return_offset = 0; + void **fixup; + void **next; /* Bail out if there is insufficient space for the epilog */ if(!jit_cache_check_for_n(&(gen->posn), 32)) @@ -793,9 +795,19 @@ void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) } #endif + /* Perform fixups on any blocks that jump to the epilog */ + inst = gen->posn.ptr; + fixup = (void **)(gen->epilog_fixup); + while(fixup != 0) + { + next = (void **)(fixup[0]); + fixup[0] = (void *)(((jit_nint)inst) - ((jit_nint)fixup) - 4); + fixup = next; + } + gen->epilog_fixup = 0; + /* If we are returning a structure via a pointer, then copy the pointer value into EAX when we return */ - inst = gen->posn.ptr; if(struct_return_offset != 0) { x86_mov_reg_membase(inst, X86_EAX, X86_EBP, struct_return_offset, 4); @@ -1208,6 +1220,100 @@ static unsigned char *setcc_reg return inst; } +/* + * Get the long form of a branch opcode. + */ +static int long_form_branch(int opcode) +{ + if(opcode == 0xEB) + { + return 0xE9; + } + else + { + return opcode + 0x0F10; + } +} + +/* + * Output a branch instruction. + */ +static unsigned char *output_branch + (jit_function_t func, unsigned char *inst, int opcode, jit_insn_t insn) +{ + jit_block_t block; + int offset; + block = jit_block_from_label(func, (jit_label_t)(insn->dest)); + if(!block) + { + return inst; + } + if(block->address) + { + /* We already know the address of the block */ + offset = ((unsigned char *)(block->address)) - (inst + 2); + if(x86_is_imm8(offset)) + { + /* We can output a short-form backwards branch */ + *inst++ = (unsigned char)opcode; + *inst++ = (unsigned char)offset; + } + else + { + /* We need to output a long-form backwards branch */ + offset -= 3; + opcode = long_form_branch(opcode); + if(opcode < 256) + { + *inst++ = (unsigned char)opcode; + } + else + { + *inst++ = (unsigned char)(opcode >> 8); + *inst++ = (unsigned char)opcode; + } + x86_imm_emit32(inst, offset); + } + } + else + { + /* Output a placeholder and record on the block's fixup list */ + opcode = long_form_branch(opcode); + if(opcode < 256) + { + *inst++ = (unsigned char)opcode; + } + else + { + *inst++ = (unsigned char)(opcode >> 8); + *inst++ = (unsigned char)opcode; + } + x86_imm_emit32(inst, (int)(block->fixup_list)); + block->fixup_list = (void *)(inst - 4); + } + return inst; +} + +/* + * Jump to the current function's epilog. + */ +static unsigned char *jump_to_epilog + (jit_gencode_t gen, unsigned char *inst, jit_block_t block) +{ + /* If the epilog is the next thing that we will output, + then fall through to the epilog directly */ + if(!(block->next)) + { + return inst; + } + + /* Output a placeholder for the jump and add it to the fixup list */ + *inst++ = (unsigned char)0xE9; + x86_imm_emit32(inst, (int)(gen->epilog_fixup)); + gen->epilog_fixup = (void *)(inst - 4); + return inst; +} + void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, jit_block_t block, jit_insn_t insn) { diff --git a/jit/jit-rules-x86.sel b/jit/jit-rules-x86.sel index a3edaf3..7cc9982 100644 --- a/jit/jit-rules-x86.sel +++ b/jit/jit-rules-x86.sel @@ -150,167 +150,167 @@ JIT_OP_ISHR_UN: binary JIT_OP_BR: spill_before [] -> { - inst = output_branch(inst, 0xE9, insn); + inst = output_branch(func, inst, 0xEB /* jmp */, insn); } JIT_OP_BR_IFALSE: unary_branch [reg] -> { x86_alu_reg_reg(inst, X86_OR, 1,ドル 1ドル); - inst = output_branch(inst, 0x74 /* eq */, insn); + inst = output_branch(func, inst, 0x74 /* eq */, insn); } JIT_OP_BR_ITRUE: unary_branch [reg] -> { x86_alu_reg_reg(inst, X86_OR, 1,ドル 1ドル); - inst = output_branch(inst, 0x75 /* ne */, insn); + inst = output_branch(func, inst, 0x75 /* ne */, insn); } JIT_OP_BR_IEQ: binary_branch [reg, immzero] -> { x86_alu_reg_reg(inst, X86_OR, 1,ドル 1ドル); - inst = output_branch(inst, 0x74 /* eq */, insn); + inst = output_branch(func, inst, 0x74 /* eq */, insn); } [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x74 /* eq */, insn); + inst = output_branch(func, inst, 0x74 /* eq */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x74 /* eq */, insn); + inst = output_branch(func, inst, 0x74 /* eq */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x74 /* eq */, insn); + inst = output_branch(func, inst, 0x74 /* eq */, insn); } JIT_OP_BR_INE: binary_branch [reg, immzero] -> { x86_alu_reg_reg(inst, X86_OR, 1,ドル 1ドル); - inst = output_branch(inst, 0x75 /* ne */, insn); + inst = output_branch(func, inst, 0x75 /* ne */, insn); } [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x75 /* ne */, insn); + inst = output_branch(func, inst, 0x75 /* ne */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x75 /* ne */, insn); + inst = output_branch(func, inst, 0x75 /* ne */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x75 /* ne */, insn); + inst = output_branch(func, inst, 0x75 /* ne */, insn); } JIT_OP_BR_ILT: binary_branch [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x7C /* lt */, insn); + inst = output_branch(func, inst, 0x7C /* lt */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x7C /* lt */, insn); + inst = output_branch(func, inst, 0x7C /* lt */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x7C /* lt */, insn); + inst = output_branch(func, inst, 0x7C /* lt */, insn); } JIT_OP_BR_ILT_UN: binary_branch [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x72 /* lt_un */, insn); + inst = output_branch(func, inst, 0x72 /* lt_un */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x72 /* lt_un */, insn); + inst = output_branch(func, inst, 0x72 /* lt_un */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x72 /* lt_un */, insn); + inst = output_branch(func, inst, 0x72 /* lt_un */, insn); } JIT_OP_BR_ILE: binary_branch [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x7E /* le */, insn); + inst = output_branch(func, inst, 0x7E /* le */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x7E /* le */, insn); + inst = output_branch(func, inst, 0x7E /* le */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x7E /* le */, insn); + inst = output_branch(func, inst, 0x7E /* le */, insn); } JIT_OP_BR_ILE_UN: binary_branch [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x76 /* le_un */, insn); + inst = output_branch(func, inst, 0x76 /* le_un */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x76 /* le_un */, insn); + inst = output_branch(func, inst, 0x76 /* le_un */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x76 /* le_un */, insn); + inst = output_branch(func, inst, 0x76 /* le_un */, insn); } JIT_OP_BR_IGT: binary_branch [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x7F /* gt */, insn); + inst = output_branch(func, inst, 0x7F /* gt */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x7F /* gt */, insn); + inst = output_branch(func, inst, 0x7F /* gt */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x7F /* gt */, insn); + inst = output_branch(func, inst, 0x7F /* gt */, insn); } JIT_OP_BR_IGT_UN: binary_branch [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x77 /* gt_un */, insn); + inst = output_branch(func, inst, 0x77 /* gt_un */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x77 /* gt_un */, insn); + inst = output_branch(func, inst, 0x77 /* gt_un */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x77 /* gt_un */, insn); + inst = output_branch(func, inst, 0x77 /* gt_un */, insn); } JIT_OP_BR_IGE: binary_branch [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x7D /* ge */, insn); + inst = output_branch(func, inst, 0x7D /* ge */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x7D /* ge */, insn); + inst = output_branch(func, inst, 0x7D /* ge */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x7D /* ge */, insn); + inst = output_branch(func, inst, 0x7D /* ge */, insn); } JIT_OP_BR_IGE_UN: binary_branch [reg, imm] -> { x86_alu_reg_imm(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x73 /* ge_un */, insn); + inst = output_branch(func, inst, 0x73 /* ge_un */, insn); } [reg, local] -> { x86_alu_reg_membase(inst, X86_CMP, 1,ドル X86_EBP, 2ドル); - inst = output_branch(inst, 0x73 /* ge_un */, insn); + inst = output_branch(func, inst, 0x73 /* ge_un */, insn); } [reg, reg] -> { x86_alu_reg_reg(inst, X86_CMP, 1,ドル 2ドル); - inst = output_branch(inst, 0x73 /* ge_un */, insn); + inst = output_branch(func, inst, 0x73 /* ge_un */, insn); } /* @@ -514,7 +514,7 @@ JIT_OP_CALL_EXTERNAL: JIT_OP_RETURN: [] -> { - inst = jump_to_epilog(gen, inst, insn); + inst = jump_to_epilog(gen, inst, block); } JIT_OP_RETURN_INT: unary_branch @@ -524,34 +524,34 @@ JIT_OP_RETURN_INT: unary_branch { x86_mov_reg_reg(inst, X86_EAX, cpu_reg, 4); } - inst = jump_to_epilog(gen, inst, insn); + inst = jump_to_epilog(gen, inst, block); } JIT_OP_RETURN_LONG: spill_before [] -> { /* TODO: load the return value into EAX:EDX */ - inst = jump_to_epilog(gen, inst, insn); + inst = jump_to_epilog(gen, inst, block); } JIT_OP_RETURN_FLOAT32: unary_branch, stack /*, only*/ [freg] -> { - inst = jump_to_epilog(gen, inst, insn); + inst = jump_to_epilog(gen, inst, block); } JIT_OP_RETURN_FLOAT64: unary_branch, stack /*, only*/ [freg] -> { - inst = jump_to_epilog(gen, inst, insn); + inst = jump_to_epilog(gen, inst, block); } JIT_OP_RETURN_NFLOAT: unary_branch, stack /*, only*/ [freg] -> { - inst = jump_to_epilog(gen, inst, insn); + inst = jump_to_epilog(gen, inst, block); } JIT_OP_RETURN_SMALL_STRUCT: spill_before [] -> { /* TODO: load the structure value into EAX:EDX */ - inst = jump_to_epilog(gen, inst, insn); + inst = jump_to_epilog(gen, inst, block); } JIT_OP_SETUP_FOR_NESTED: spill_before diff --git a/jit/jit-rules.h b/jit/jit-rules.h index 7b48b58..3bad408 100644 --- a/jit/jit-rules.h +++ b/jit/jit-rules.h @@ -137,6 +137,7 @@ struct jit_gencode #ifdef jit_extra_gen_state jit_extra_gen_state; /* CPU-specific extra information */ #endif + void *epilog_fixup; /* Fixup list for function epilogs */ }; /* diff --git a/tools/gen-sel-parser.y b/tools/gen-sel-parser.y index fbc78f5..ed4444c 100644 --- a/tools/gen-sel-parser.y +++ b/tools/gen-sel-parser.y @@ -549,8 +549,8 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options) if((options & (GENSEL_OPT_BINARY_BRANCH | GENSEL_OPT_UNARY_BRANCH)) != 0) { - /* Spill all registers back to their original positions */ - printf("\t\t_jit_gen_spill_all(gen);\n"); + /* Spill all other registers back to their original positions */ + printf("\t\t_jit_regs_spill_all(gen);\n"); } gensel_output_clause(clause); printf("\t}\n"); |