summaryrefslogtreecommitdiff
path: root/py/emitnative.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/emitnative.c')
-rw-r--r--py/emitnative.c93
1 files changed, 34 insertions, 59 deletions
diff --git a/py/emitnative.c b/py/emitnative.c
index bfb37ef4f..ddc0b5b97 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -231,9 +231,7 @@ struct _emit_t {
exc_stack_entry_t *exc_stack;
int prelude_offset;
- #if N_PRELUDE_AS_BYTES_OBJ
- size_t prelude_const_table_offset;
- #endif
+ int prelude_ptr_index;
int start_offset;
int n_state;
uint16_t code_state_start;
@@ -349,16 +347,6 @@ STATIC void emit_native_mov_reg_qstr_obj(emit_t *emit, int reg_dest, qstr qst) {
STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
- if (pass == MP_PASS_SCOPE) {
- // Note: the first argument passed here is mp_emit_common_t, not the native emitter context
- #if N_PRELUDE_AS_BYTES_OBJ
- if (scope->emit_options == MP_EMIT_OPT_NATIVE_PYTHON) {
- mp_emit_common_alloc_const_obj((mp_emit_common_t *)emit, mp_const_none);
- }
- #endif
- return;
- }
-
emit->pass = pass;
emit->do_viper_types = scope->emit_options == MP_EMIT_OPT_VIPER;
emit->stack_size = 0;
@@ -511,12 +499,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
emit->code_state_start = 0;
emit->stack_start = SIZEOF_CODE_STATE;
- #if N_PRELUDE_AS_BYTES_OBJ
- // Load index of prelude bytes object in const_table
- mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_const_table_offset);
- #else
- mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_offset);
- #endif
+ mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_ptr_index);
mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->start_offset);
ASM_ENTRY(emit->as, SIZEOF_NLR_BUF);
@@ -562,41 +545,19 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
// Set code_state.fun_bc
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1);
- // Set code_state.ip, a pointer to the beginning of the prelude
+ // Set code_state.ip, a pointer to the beginning of the prelude. This pointer is found
+ // either directly in mp_obj_fun_bc_t.child_table (if there are no children), or in
+ // mp_obj_fun_bc_t.child_table[num_children] (if num_children > 0).
// Need to use some locals for this, so assert that they are available for use
MP_STATIC_ASSERT(REG_LOCAL_3 != REG_PARENT_ARG_1);
MP_STATIC_ASSERT(REG_LOCAL_3 != REG_PARENT_ARG_2);
MP_STATIC_ASSERT(REG_LOCAL_3 != REG_PARENT_ARG_3);
MP_STATIC_ASSERT(REG_LOCAL_3 != REG_PARENT_ARG_4);
- int code_state_ip_local = emit->code_state_start + OFFSETOF_CODE_STATE_IP;
- #if N_PRELUDE_AS_BYTES_OBJ
- // Prelude is a bytes object in const_table[prelude_const_table_offset].
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, emit->prelude_const_table_offset);
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, offsetof(mp_obj_str_t, data) / sizeof(uintptr_t));
- #else
- MP_STATIC_ASSERT(REG_LOCAL_2 != REG_PARENT_ARG_1);
- MP_STATIC_ASSERT(REG_LOCAL_2 != REG_PARENT_ARG_2);
- MP_STATIC_ASSERT(REG_LOCAL_2 != REG_PARENT_ARG_3);
- MP_STATIC_ASSERT(REG_LOCAL_2 != REG_PARENT_ARG_4);
- // Prelude is at the end of the machine code
- ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_BYTECODE);
- if (emit->pass == MP_PASS_CODE_SIZE) {
- // Commit to the encoding size based on the value of prelude_offset in this pass.
- // By using 32768 as the cut-off it is highly unlikely that prelude_offset will
- // grow beyond 65535 by the end of thiss pass, and so require the larger encoding.
- emit->prelude_offset_uses_u16_encoding = emit->prelude_offset < 32768;
- }
- if (emit->prelude_offset_uses_u16_encoding) {
- assert(emit->prelude_offset <= 65535);
- ASM_MOV_REG_IMM_FIX_U16((emit)->as, REG_LOCAL_2, emit->prelude_offset);
- } else {
- ASM_MOV_REG_IMM_FIX_WORD((emit)->as, REG_LOCAL_2, emit->prelude_offset);
+ ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CHILD_TABLE);
+ if (emit->prelude_ptr_index != 0) {
+ ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, emit->prelude_ptr_index);
}
- ASM_ADD_REG_REG(emit->as, REG_LOCAL_3, REG_LOCAL_2);
- #endif
- emit_native_mov_state_reg(emit, code_state_ip_local, REG_LOCAL_3);
+ emit_native_mov_state_reg(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, REG_LOCAL_3);
// Set code_state.n_state (only works on little endian targets due to n_state being uint16_t)
emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_N_STATE, emit->n_state, REG_ARG_1);
@@ -657,6 +618,7 @@ STATIC bool emit_native_end_pass(emit_t *emit) {
if (!emit->do_viper_types) {
emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base);
+ emit->prelude_ptr_index = emit->emit_common->ct_cur_child;
size_t n_state = emit->n_state;
size_t n_exc_stack = 0; // exc-stack not needed for native code
@@ -693,16 +655,6 @@ STATIC bool emit_native_end_pass(emit_t *emit) {
}
emit->n_cell = mp_asm_base_get_code_pos(&emit->as->base) - cell_start;
- #if N_PRELUDE_AS_BYTES_OBJ
- // Create the prelude as a bytes object, and store it in the constant table
- mp_obj_t prelude = mp_const_none;
- if (emit->pass == MP_PASS_EMIT) {
- void *buf = emit->as->base.code_base + emit->prelude_offset;
- size_t n = emit->as->base.code_offset - emit->prelude_offset;
- prelude = mp_obj_new_bytes(buf, n);
- }
- emit->prelude_const_table_offset = mp_emit_common_alloc_const_obj(emit->emit_common, prelude);
- #endif
}
ASM_END_PASS(emit->as);
@@ -725,10 +677,33 @@ STATIC bool emit_native_end_pass(emit_t *emit) {
void *f = mp_asm_base_get_code(&emit->as->base);
mp_uint_t f_len = mp_asm_base_get_code_size(&emit->as->base);
+ mp_raw_code_t **children = emit->emit_common->children;
+ if (!emit->do_viper_types) {
+ #if MICROPY_EMIT_NATIVE_PRELUDE_SEPARATE_FROM_MACHINE_CODE
+ // Executable code cannot be accessed byte-wise on this architecture, so copy
+ // the prelude to a separate memory region that is byte-wise readable.
+ void *buf = emit->as->base.code_base + emit->prelude_offset;
+ size_t n = emit->as->base.code_offset - emit->prelude_offset;
+ const uint8_t *prelude_ptr = memcpy(m_new(uint8_t, n), buf, n);
+ #else
+ // Point to the prelude directly, at the end of the machine code data.
+ const uint8_t *prelude_ptr = (const uint8_t *)f + emit->prelude_offset;
+ #endif
+
+ // Store the pointer to the prelude using the child_table.
+ assert(emit->prelude_ptr_index == emit->emit_common->ct_cur_child);
+ if (emit->prelude_ptr_index == 0) {
+ children = (void *)prelude_ptr;
+ } else {
+ children = m_renew(mp_raw_code_t *, children, emit->prelude_ptr_index, emit->prelude_ptr_index + 1);
+ children[emit->prelude_ptr_index] = (void *)prelude_ptr;
+ }
+ }
+
mp_emit_glue_assign_native(emit->scope->raw_code,
emit->do_viper_types ? MP_CODE_NATIVE_VIPER : MP_CODE_NATIVE_PY,
f, f_len,
- emit->emit_common->children,
+ children,
#if MICROPY_PERSISTENT_CODE_SAVE
emit->emit_common->ct_cur_child,
emit->prelude_offset,