py/asmx86: Change indirect calls to load fun ptr from the native table.

Instead of storing the function pointer directly in the assembly code.
This makes the generated code more independent of the runtime (so easier to
relocate the code), and reduces the generated code size.
This commit is contained in:
Damien George 2018-10-13 13:59:19 +11:00
parent b7c6f859d0
commit 355eb8eafb
3 changed files with 10 additions and 16 deletions

View File

@ -494,7 +494,7 @@ void asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32)
} }
#endif #endif
void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32) { void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r32) {
// TODO align stack on 16-byte boundary before the call // TODO align stack on 16-byte boundary before the call
assert(n_args <= 5); assert(n_args <= 5);
if (n_args > 4) { if (n_args > 4) {
@ -512,20 +512,10 @@ void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32)
if (n_args > 0) { if (n_args > 0) {
asm_x86_push_r32(as, ASM_X86_REG_ARG_1); asm_x86_push_r32(as, ASM_X86_REG_ARG_1);
} }
#ifdef __LP64__
// We wouldn't run x86 code on an x64 machine. This is here to enable // Load the pointer to the function and make the call
// testing of the x86 emitter only. asm_x86_mov_mem32_to_r32(as, ASM_X86_REG_EBP, fun_id * WORD_SIZE, temp_r32);
asm_x86_mov_i32_to_r32(as, (int32_t)(int64_t)ptr, temp_r32);
#else
// If we get here, sizeof(int) == sizeof(void*).
asm_x86_mov_i32_to_r32(as, (int32_t)ptr, temp_r32);
#endif
asm_x86_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R32(2) | MODRM_RM_REG | MODRM_RM_R32(temp_r32)); asm_x86_write_byte_2(as, OPCODE_CALL_RM32, MODRM_R32(2) | MODRM_RM_REG | MODRM_RM_R32(temp_r32));
// this reduces code size by 2 bytes per call, but doesn't seem to speed it up at all
/*
asm_x86_write_byte_1(as, OPCODE_CALL_REL32);
asm_x86_write_word32(as, ptr - (void*)(as->code_base + as->base.code_offset + 4));
*/
// the caller must clean up the stack // the caller must clean up the stack
if (n_args > 0) { if (n_args > 0) {

View File

@ -112,7 +112,7 @@ void asm_x86_mov_local_to_r32(asm_x86_t* as, int src_local_num, int dest_r32);
void asm_x86_mov_r32_to_local(asm_x86_t* as, int src_r32, int dest_local_num); void asm_x86_mov_r32_to_local(asm_x86_t* as, int src_r32, int dest_local_num);
void asm_x86_mov_local_addr_to_r32(asm_x86_t* as, int local_num, int dest_r32); void asm_x86_mov_local_addr_to_r32(asm_x86_t* as, int local_num, int dest_r32);
void asm_x86_mov_reg_pcrel(asm_x86_t *as, int dest_r64, mp_uint_t label); void asm_x86_mov_reg_pcrel(asm_x86_t *as, int dest_r64, mp_uint_t label);
void asm_x86_call_ind(asm_x86_t* as, void* ptr, mp_uint_t n_args, int temp_r32); void asm_x86_call_ind(asm_x86_t* as, size_t fun_id, mp_uint_t n_args, int temp_r32);
#if GENERIC_ASM_API #if GENERIC_ASM_API
@ -169,7 +169,7 @@ void asm_x86_call_ind(asm_x86_t* as, void* ptr, mp_uint_t n_args, int temp_r32);
asm_x86_jcc_label(as, ASM_X86_CC_JE, label); \ asm_x86_jcc_label(as, ASM_X86_CC_JE, label); \
} while (0) } while (0)
#define ASM_JUMP_REG(as, reg) asm_x86_jmp_reg((as), (reg)) #define ASM_JUMP_REG(as, reg) asm_x86_jmp_reg((as), (reg))
#define ASM_CALL_IND(as, ptr, idx) asm_x86_call_ind(as, ptr, mp_f_n_args[idx], ASM_X86_REG_EAX) #define ASM_CALL_IND(as, ptr, idx) asm_x86_call_ind(as, idx, mp_f_n_args[idx], ASM_X86_REG_EAX)
#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x86_mov_r32_to_local((as), (reg_src), (local_num)) #define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x86_mov_r32_to_local((as), (reg_src), (local_num))
#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32((as), (imm), (reg_dest)) #define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32((as), (imm), (reg_dest))

View File

@ -379,6 +379,8 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
asm_arm_mov_reg_i32(emit->as, ASM_ARM_REG_R7, (mp_uint_t)mp_fun_table); asm_arm_mov_reg_i32(emit->as, ASM_ARM_REG_R7, (mp_uint_t)mp_fun_table);
#elif N_XTENSA #elif N_XTENSA
ASM_MOV_REG_IMM(emit->as, ASM_XTENSA_REG_A15, (uint32_t)mp_fun_table); ASM_MOV_REG_IMM(emit->as, ASM_XTENSA_REG_A15, (uint32_t)mp_fun_table);
#elif N_X86
asm_x86_mov_i32_to_r32(emit->as, (intptr_t)mp_fun_table, ASM_X86_REG_EBP);
#elif N_X64 #elif N_X64
asm_x64_mov_i64_to_r64_optimised(emit->as, (intptr_t)mp_fun_table, ASM_X64_REG_RBP); asm_x64_mov_i64_to_r64_optimised(emit->as, (intptr_t)mp_fun_table, ASM_X64_REG_RBP);
#endif #endif
@ -471,6 +473,8 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
asm_arm_mov_reg_i32(emit->as, ASM_ARM_REG_R7, (mp_uint_t)mp_fun_table); asm_arm_mov_reg_i32(emit->as, ASM_ARM_REG_R7, (mp_uint_t)mp_fun_table);
#elif N_XTENSA #elif N_XTENSA
ASM_MOV_REG_IMM(emit->as, ASM_XTENSA_REG_A15, (uint32_t)mp_fun_table); ASM_MOV_REG_IMM(emit->as, ASM_XTENSA_REG_A15, (uint32_t)mp_fun_table);
#elif N_X86
asm_x86_mov_i32_to_r32(emit->as, (intptr_t)mp_fun_table, ASM_X86_REG_EBP);
#elif N_X64 #elif N_X64
asm_x64_mov_i64_to_r64_optimised(emit->as, (intptr_t)mp_fun_table, ASM_X64_REG_RBP); asm_x64_mov_i64_to_r64_optimised(emit->as, (intptr_t)mp_fun_table, ASM_X64_REG_RBP);
#endif #endif