Skip to content

Commit 4107597

Browse files
committed
py/emitnative: Add support for archs with windowed registers.
Such that args/return regs for the parent are different to args/return regs for child calls. For an architecture to use this feature it should define the REG_PARENT_xxx macros before including py/emitnative.c.
1 parent 27fe84e commit 4107597

File tree

1 file changed

+45
-22
lines changed

1 file changed

+45
-22
lines changed

py/emitnative.c

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@
9494
#define OFFSETOF_OBJ_FUN_BC_GLOBALS (offsetof(mp_obj_fun_bc_t, globals) / sizeof(uintptr_t))
9595
#define OFFSETOF_OBJ_FUN_BC_CONST_TABLE (offsetof(mp_obj_fun_bc_t, const_table) / sizeof(uintptr_t))
9696

97+
// If not already defined, set parent args to same as child call registers
98+
#ifndef REG_PARENT_RET
99+
#define REG_PARENT_RET REG_RET
100+
#define REG_PARENT_ARG_1 REG_ARG_1
101+
#define REG_PARENT_ARG_2 REG_ARG_2
102+
#define REG_PARENT_ARG_3 REG_ARG_3
103+
#define REG_PARENT_ARG_4 REG_ARG_4
104+
#endif
105+
97106
// Word index of nlr_buf_t.ret_val
98107
#define NLR_BUF_IDX_RET_VAL (1)
99108

@@ -413,16 +422,16 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
413422
ASM_ENTRY(emit->as, emit->stack_start + emit->n_state - num_locals_in_regs);
414423

415424
#if N_X86
416-
asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_1);
425+
asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1);
417426
#endif
418427

419428
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
420-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE);
429+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE);
421430
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_LOCAL_3, 0);
422431

423432
// Store function object (passed as first arg) to stack if needed
424433
if (NEED_FUN_OBJ(emit)) {
425-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_ARG_1);
434+
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1);
426435
}
427436

428437
// Put n_args in REG_ARG_1, n_kw in REG_ARG_2, args array in REG_LOCAL_3
@@ -431,9 +440,9 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
431440
asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_2);
432441
asm_x86_mov_arg_to_r32(emit->as, 3, REG_LOCAL_3);
433442
#else
434-
ASM_MOV_REG_REG(emit->as, REG_ARG_1, REG_ARG_2);
435-
ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_ARG_3);
436-
ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_4);
443+
ASM_MOV_REG_REG(emit->as, REG_ARG_1, REG_PARENT_ARG_2);
444+
ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_PARENT_ARG_3);
445+
ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_PARENT_ARG_4);
437446
#endif
438447

439448
// Check number of args matches this function, and call mp_arg_check_num_sig if not
@@ -482,14 +491,14 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
482491
#if N_X86
483492
asm_x86_mov_arg_to_r32(emit->as, 0, REG_GENERATOR_STATE);
484493
#else
485-
ASM_MOV_REG_REG(emit->as, REG_GENERATOR_STATE, REG_ARG_1);
494+
ASM_MOV_REG_REG(emit->as, REG_GENERATOR_STATE, REG_PARENT_ARG_1);
486495
#endif
487496

488497
// Put throw value into LOCAL_IDX_EXC_VAL slot, for yield/yield-from
489498
#if N_X86
490-
asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_2);
499+
asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2);
491500
#endif
492-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_ARG_2);
501+
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_PARENT_ARG_2);
493502

494503
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
495504
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, LOCAL_IDX_FUN_OBJ(emit));
@@ -505,29 +514,40 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
505514
// Prepare incoming arguments for call to mp_setup_code_state
506515

507516
#if N_X86
508-
asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_1);
509-
asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_2);
510-
asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_3);
511-
asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_4);
517+
asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1);
518+
asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2);
519+
asm_x86_mov_arg_to_r32(emit->as, 2, REG_PARENT_ARG_3);
520+
asm_x86_mov_arg_to_r32(emit->as, 3, REG_PARENT_ARG_4);
512521
#endif
513522

514523
// Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table
515-
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE);
524+
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE);
516525
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_LOCAL_3, emit->scope->num_pos_args + emit->scope->num_kwonly_args);
517526

518527
// Set code_state.fun_bc
519-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_ARG_1);
528+
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1);
520529

521530
// Set code_state.ip (offset from start of this function to prelude info)
522531
// TODO this encoding may change size in the final pass, need to make it fixed
523-
emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, emit->prelude_offset, REG_ARG_1);
532+
emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, emit->prelude_offset, REG_PARENT_ARG_1);
524533

525534
// Set code_state.n_state (only works on little endian targets due to n_state being uint16_t)
526535
emit_native_mov_state_imm_via(emit, emit->code_state_start + offsetof(mp_code_state_t, n_state) / sizeof(uintptr_t), emit->n_state, REG_ARG_1);
527536

528537
// Put address of code_state into first arg
529538
ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, emit->code_state_start);
530539

540+
// Copy next 3 args if needed
541+
#if REG_ARG_2 != REG_PARENT_ARG_2
542+
ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_PARENT_ARG_2);
543+
#endif
544+
#if REG_ARG_3 != REG_PARENT_ARG_3
545+
ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_PARENT_ARG_3);
546+
#endif
547+
#if REG_ARG_4 != REG_PARENT_ARG_4
548+
ASM_MOV_REG_REG(emit->as, REG_ARG_4, REG_PARENT_ARG_4);
549+
#endif
550+
531551
// Call mp_setup_code_state to prepare code_state structure
532552
#if N_THUMB
533553
asm_thumb_bl_ind(emit->as, MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4);
@@ -1174,7 +1194,7 @@ STATIC void emit_native_global_exc_entry(emit_t *emit) {
11741194
ASM_STORE_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, OFFSETOF_CODE_STATE_STATE);
11751195

11761196
// Load return kind
1177-
ASM_MOV_REG_IMM(emit->as, REG_RET, MP_VM_RETURN_EXCEPTION);
1197+
ASM_MOV_REG_IMM(emit->as, REG_PARENT_RET, MP_VM_RETURN_EXCEPTION);
11781198

11791199
ASM_EXIT(emit->as);
11801200
} else {
@@ -1229,7 +1249,7 @@ STATIC void emit_native_global_exc_exit(emit_t *emit) {
12291249
}
12301250

12311251
// Load return value
1232-
ASM_MOV_REG_LOCAL(emit->as, REG_RET, LOCAL_IDX_RET_VAL(emit));
1252+
ASM_MOV_REG_LOCAL(emit->as, REG_PARENT_RET, LOCAL_IDX_RET_VAL(emit));
12331253
}
12341254

12351255
ASM_EXIT(emit->as);
@@ -2617,13 +2637,13 @@ STATIC void emit_native_return_value(emit_t *emit) {
26172637
if (peek_vtype(emit, 0) == VTYPE_PTR_NONE) {
26182638
emit_pre_pop_discard(emit);
26192639
if (return_vtype == VTYPE_PYOBJ) {
2620-
emit_native_mov_reg_const(emit, REG_RET, MP_F_CONST_NONE_OBJ);
2640+
emit_native_mov_reg_const(emit, REG_PARENT_RET, MP_F_CONST_NONE_OBJ);
26212641
} else {
26222642
ASM_MOV_REG_IMM(emit->as, REG_ARG_1, 0);
26232643
}
26242644
} else {
26252645
vtype_kind_t vtype;
2626-
emit_pre_pop_reg(emit, &vtype, return_vtype == VTYPE_PYOBJ ? REG_RET : REG_ARG_1);
2646+
emit_pre_pop_reg(emit, &vtype, return_vtype == VTYPE_PYOBJ ? REG_PARENT_RET : REG_ARG_1);
26272647
if (vtype != return_vtype) {
26282648
EMIT_NATIVE_VIPER_TYPE_ERROR(emit,
26292649
"return expected '%q' but got '%q'",
@@ -2632,15 +2652,18 @@ STATIC void emit_native_return_value(emit_t *emit) {
26322652
}
26332653
if (return_vtype != VTYPE_PYOBJ) {
26342654
emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, return_vtype, REG_ARG_2);
2655+
#if REG_RET != REG_PARENT_ARG_RET
2656+
ASM_MOV_REG_REG(emit->as, REG_PARENT_RET, REG_RET);
2657+
#endif
26352658
}
26362659
} else {
26372660
vtype_kind_t vtype;
2638-
emit_pre_pop_reg(emit, &vtype, REG_RET);
2661+
emit_pre_pop_reg(emit, &vtype, REG_PARENT_RET);
26392662
assert(vtype == VTYPE_PYOBJ);
26402663
}
26412664
if (NEED_GLOBAL_EXC_HANDLER(emit)) {
26422665
// Save return value for the global exception handler to use
2643-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_RET);
2666+
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_PARENT_RET);
26442667
}
26452668
emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size);
26462669
emit->last_emit_was_return_value = true;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy