diff --git a/py/asmthumb.c b/py/asmthumb.c index c739a6dd25..a21a3da309 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -42,7 +42,7 @@ #define SIGNED_FIT12(x) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800) struct _asm_thumb_t { - int pass; + uint pass; uint code_offset; uint code_size; byte *code_base; @@ -58,14 +58,9 @@ struct _asm_thumb_t { asm_thumb_t *asm_thumb_new(uint max_num_labels) { asm_thumb_t *as; - as = m_new(asm_thumb_t, 1); - as->pass = 0; - as->code_offset = 0; - as->code_size = 0; - as->code_base = NULL; + as = m_new0(asm_thumb_t, 1); as->max_num_labels = max_num_labels; as->label_offsets = m_new(int, max_num_labels); - as->num_locals = 0; return as; } @@ -89,16 +84,16 @@ void asm_thumb_free(asm_thumb_t *as, bool free_code) { m_del_obj(asm_thumb_t, as); } -void asm_thumb_start_pass(asm_thumb_t *as, int pass) { +void asm_thumb_start_pass(asm_thumb_t *as, uint pass) { as->pass = pass; as->code_offset = 0; - if (pass == ASM_THUMB_PASS_2) { + if (pass == ASM_THUMB_PASS_COMPUTE) { memset(as->label_offsets, -1, as->max_num_labels * sizeof(int)); } } void asm_thumb_end_pass(asm_thumb_t *as) { - if (as->pass == ASM_THUMB_PASS_2) { + if (as->pass == ASM_THUMB_PASS_COMPUTE) { // calculate size of code in bytes as->code_size = as->code_offset; as->code_base = m_new(byte, as->code_size); @@ -120,7 +115,7 @@ void asm_thumb_end_pass(asm_thumb_t *as) { // all functions must go through this one to emit bytes STATIC byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int num_bytes_to_write) { //printf("emit %d\n", num_bytes_to_write); - if (as->pass < ASM_THUMB_PASS_3) { + if (as->pass < ASM_THUMB_PASS_EMIT) { as->code_offset += num_bytes_to_write; return as->dummy_data; } else { @@ -224,12 +219,12 @@ void asm_thumb_exit(asm_thumb_t *as) { void asm_thumb_label_assign(asm_thumb_t *as, uint label) { assert(label < as->max_num_labels); - if (as->pass == ASM_THUMB_PASS_2) { + if (as->pass < ASM_THUMB_PASS_EMIT) { // assign label offset assert(as->label_offsets[label] == -1); as->label_offsets[label] = as->code_offset; - } else if (as->pass == ASM_THUMB_PASS_3) { - // ensure label offset has not changed from PASS_2 to PASS_3 + } else { + // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT //printf("l%d: (at %d=%ld)\n", label, as->label_offsets[label], as->code_offset); assert(as->label_offsets[label] == as->code_offset); } @@ -383,20 +378,35 @@ void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) { } } +// i32 is stored as a full word in the code, and aligned to machine-word boundary +// TODO this is very inefficient, improve it! +void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) { + // align on machine-word + 2 + if ((as->code_offset & 3) == 0) { + asm_thumb_op16(as, ASM_THUMB_OP_NOP); + } + // jump over the i32 value (instruction prefect adds 4 to PC) + asm_thumb_op16(as, OP_B_N(0)); + // store i32 on machine-word aligned boundary + asm_thumb_data(as, 4, i32); + // do the actual load of the i32 value + asm_thumb_mov_reg_i32_optimised(as, reg_dest, i32); +} + #define OP_STR_TO_SP_OFFSET(rlo_dest, word_offset) (0x9000 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff)) #define OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset) (0x9800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff)) void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num, uint rlo_src) { assert(rlo_src < REG_R8); int word_offset = as->num_locals - local_num - 1; - assert(as->pass < ASM_THUMB_PASS_3 || word_offset >= 0); + assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_STR_TO_SP_OFFSET(rlo_src, word_offset)); } void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) { assert(rlo_dest < REG_R8); int word_offset = as->num_locals - local_num - 1; - assert(as->pass < ASM_THUMB_PASS_3 || word_offset >= 0); + assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset)); } @@ -405,7 +415,7 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) { void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num) { assert(rlo_dest < REG_R8); int word_offset = as->num_locals - local_num - 1; - assert(as->pass < ASM_THUMB_PASS_3 || word_offset >= 0); + assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset)); } diff --git a/py/asmthumb.h b/py/asmthumb.h index fbc3754387..1046b0353b 100644 --- a/py/asmthumb.h +++ b/py/asmthumb.h @@ -24,9 +24,8 @@ * THE SOFTWARE. */ -#define ASM_THUMB_PASS_1 (1) -#define ASM_THUMB_PASS_2 (2) -#define ASM_THUMB_PASS_3 (3) +#define ASM_THUMB_PASS_COMPUTE (1) +#define ASM_THUMB_PASS_EMIT (2) #define REG_R0 (0) #define REG_R1 (1) @@ -71,7 +70,7 @@ typedef struct _asm_thumb_t asm_thumb_t; asm_thumb_t *asm_thumb_new(uint max_num_labels); void asm_thumb_free(asm_thumb_t *as, bool free_code); -void asm_thumb_start_pass(asm_thumb_t *as, int pass); +void asm_thumb_start_pass(asm_thumb_t *as, uint pass); void asm_thumb_end_pass(asm_thumb_t *as); uint asm_thumb_get_code_size(asm_thumb_t *as); void *asm_thumb_get_code(asm_thumb_t *as); @@ -188,6 +187,7 @@ void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label); void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32_src); // convenience void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32_src); // convenience +void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32); // convenience void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src); // convenience void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience diff --git a/py/asmx64.c b/py/asmx64.c index 7c279c521b..6c22ea25de 100644 --- a/py/asmx64.c +++ b/py/asmx64.c @@ -112,7 +112,7 @@ #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) struct _asm_x64_t { - int pass; + uint pass; uint code_offset; uint code_size; byte *code_base; @@ -138,14 +138,9 @@ void *alloc_mem(uint req_size, uint *alloc_size, bool is_exec) { asm_x64_t *asm_x64_new(uint max_num_labels) { asm_x64_t *as; - as = m_new(asm_x64_t, 1); - as->pass = 0; - as->code_offset = 0; - as->code_size = 0; - as->code_base = NULL; + as = m_new0(asm_x64_t, 1); as->max_num_labels = max_num_labels; as->label_offsets = m_new(int, max_num_labels); - as->num_locals = 0; return as; } @@ -170,17 +165,17 @@ void asm_x64_free(asm_x64_t *as, bool free_code) { m_del_obj(asm_x64_t, as); } -void asm_x64_start_pass(asm_x64_t *as, int pass) { +void asm_x64_start_pass(asm_x64_t *as, uint pass) { as->pass = pass; as->code_offset = 0; - if (pass == ASM_X64_PASS_2) { + if (pass == ASM_X64_PASS_COMPUTE) { // reset all labels memset(as->label_offsets, -1, as->max_num_labels * sizeof(int)); } } void asm_x64_end_pass(asm_x64_t *as) { - if (as->pass == ASM_X64_PASS_2) { + if (as->pass == ASM_X64_PASS_COMPUTE) { // calculate size of code in bytes as->code_size = as->code_offset; //as->code_base = m_new(byte, as->code_size); need to allocale executable memory @@ -204,7 +199,7 @@ void asm_x64_end_pass(asm_x64_t *as) { // all functions must go through this one to emit bytes STATIC byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int num_bytes_to_write) { //printf("emit %d\n", num_bytes_to_write); - if (as->pass < ASM_X64_PASS_3) { + if (as->pass < ASM_X64_PASS_EMIT) { as->code_offset += num_bytes_to_write; return as->dummy_data; } else { @@ -367,6 +362,15 @@ void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r } } +// src_i64 is stored as a full word in the code, and aligned to machine-word boundary +void asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64) { + // mov instruction uses 2 bytes for the instruction, before the i64 + while (((as->code_offset + 2) & (WORD_SIZE - 1)) != 0) { + asm_x64_nop(as); + } + asm_x64_mov_i64_to_r64(as, src_i64, dest_r64); +} + void asm_x64_mov_i32_to_disp(asm_x64_t *as, int src_i32, int dest_r32, int dest_disp) { assert(0); @@ -487,12 +491,12 @@ void asm_x64_setcc_r8(asm_x64_t *as, int jcc_type, int dest_r8) { void asm_x64_label_assign(asm_x64_t *as, int label) { assert(label < as->max_num_labels); - if (as->pass == ASM_X64_PASS_2) { + if (as->pass < ASM_X64_PASS_EMIT) { // assign label offset assert(as->label_offsets[label] == -1); as->label_offsets[label] = as->code_offset; - } else if (as->pass == ASM_X64_PASS_3) { - // ensure label offset has not changed from PASS_2 to PASS_3 + } else { + // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT //printf("l%d: (at %d=%ld)\n", label, as->label_offsets[label], as->code_offset); assert(as->label_offsets[label] == as->code_offset); } diff --git a/py/asmx64.h b/py/asmx64.h index 9c45fa1747..1d5d6c7c21 100644 --- a/py/asmx64.h +++ b/py/asmx64.h @@ -24,9 +24,8 @@ * THE SOFTWARE. */ -#define ASM_X64_PASS_1 (1) -#define ASM_X64_PASS_2 (2) -#define ASM_X64_PASS_3 (3) +#define ASM_X64_PASS_COMPUTE (1) +#define ASM_X64_PASS_EMIT (2) #define REG_RAX (0) #define REG_RCX (1) @@ -54,7 +53,7 @@ typedef struct _asm_x64_t asm_x64_t; asm_x64_t* asm_x64_new(uint max_num_labels); void asm_x64_free(asm_x64_t* as, bool free_code); -void asm_x64_start_pass(asm_x64_t *as, int pass); +void asm_x64_start_pass(asm_x64_t *as, uint pass); void asm_x64_end_pass(asm_x64_t *as); uint asm_x64_get_code_size(asm_x64_t* as); void* asm_x64_get_code(asm_x64_t* as); @@ -71,6 +70,7 @@ void asm_x64_mov_i32_to_r64(asm_x64_t* as, int src_i32, int dest_r64); void asm_x64_mov_i64_to_r64(asm_x64_t* as, int64_t src_i64, int dest_r64); void asm_x64_mov_i32_to_disp(asm_x64_t* as, int src_i32, int dest_r32, int dest_disp); void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r64); +void asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64); void asm_x64_xor_r64_to_r64(asm_x64_t *as, int src_r64, int dest_r64); void asm_x64_add_r64_to_r64(asm_x64_t* as, int src_r64, int dest_r64); void asm_x64_add_i32_to_r32(asm_x64_t* as, int src_i32, int dest_r32); diff --git a/py/compile.c b/py/compile.c index 9a660e2ef5..bc9d7aeb4c 100644 --- a/py/compile.c +++ b/py/compile.c @@ -994,7 +994,7 @@ void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) { // leaves function object on stack // returns function name qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this function scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options); // store the function scope so the compiling function can use it at each pass @@ -1043,7 +1043,7 @@ qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint // leaves class object on stack // returns class name qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this class scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options); // store the class scope so the compiling function can use it at each pass @@ -1510,7 +1510,7 @@ void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { } void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) { scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); } else { @@ -1524,7 +1524,7 @@ void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) { scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); } else { @@ -2056,7 +2056,7 @@ void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t*)pns1->nodes[0])->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(((mp_parse_node_struct_t*)pns1->nodes[0])->nodes[2]) ) { - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { qstr const_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); if (!MP_PARSE_NODE_IS_SMALL_INT(((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pns1->nodes[0])->nodes[1])->nodes[0])) { @@ -2153,7 +2153,7 @@ void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) { //mp_parse_node_t pn_params = pns->nodes[0]; //mp_parse_node_t pn_body = pns->nodes[1]; - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this lambda scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options); // store the lambda scope so the compiling function (this one) can use it at each pass @@ -2499,7 +2499,7 @@ void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_ assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1]; - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this comprehension scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options); // store the comprehension scope so the compiling function (this one) can use it at each pass @@ -3020,7 +3020,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { comp->next_label = 1; EMIT_ARG(start_pass, pass, scope); - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { // reset maximum stack sizes in scope // they will be computed in this first pass scope->stack_size = 0; @@ -3028,7 +3028,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { } #if MICROPY_EMIT_CPYTHON - if (comp->pass == PASS_3) { + if (comp->pass == MP_PASS_EMIT) { scope_print_info(scope); } #endif @@ -3053,7 +3053,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { // work out number of parameters, keywords and default parameters, and add them to the id_info array // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { comp->have_star = false; apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param); } @@ -3073,7 +3073,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { // work out number of parameters, keywords and default parameters, and add them to the id_info array // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { comp->have_star = false; apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param); } @@ -3104,7 +3104,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { #else qstr qstr_arg = MP_QSTR_; #endif - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { bool added; id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added); assert(added); @@ -3141,7 +3141,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef); - if (comp->pass == PASS_1) { + if (comp->pass == MP_PASS_SCOPE) { bool added; id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added); assert(added); @@ -3177,6 +3177,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { } #if MICROPY_EMIT_INLINE_THUMB +// requires 3 passes: SCOPE, CODE_SIZE, EMIT STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) { comp->pass = pass; comp->scope_cur = scope; @@ -3187,7 +3188,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind return; } - if (comp->pass > PASS_1) { + if (comp->pass > MP_PASS_SCOPE) { EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur); } @@ -3199,7 +3200,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name // parameters are in pns->nodes[1] - if (comp->pass == PASS_2) { + if (comp->pass == MP_PASS_CODE_SIZE) { mp_parse_node_t *pn_params; int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params); scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params); @@ -3212,7 +3213,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind int num = list_get(&pn_body, PN_suite_block_stmts, &nodes); /* - if (comp->pass == PASS_3) { + if (comp->pass == MP_PASS_EMIT) { //printf("----\n"); scope_print_info(scope); } @@ -3250,7 +3251,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind return; } uint lab = comp_next_label(comp); - if (pass > PASS_1) { + if (pass > MP_PASS_SCOPE) { EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0])); } } else if (op == MP_QSTR_align) { @@ -3258,7 +3259,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind compile_syntax_error(comp, nodes[i], "inline assembler 'align' requires 1 argument"); return; } - if (pass > PASS_1) { + if (pass > MP_PASS_SCOPE) { EMIT_INLINE_ASM_ARG(align, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0])); } } else if (op == MP_QSTR_data) { @@ -3266,7 +3267,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires at least 2 arguments"); return; } - if (pass > PASS_1) { + if (pass > MP_PASS_SCOPE) { machine_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]); for (uint i = 1; i < n_args; i++) { if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[i])) { @@ -3277,13 +3278,13 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind } } } else { - if (pass > PASS_1) { + if (pass > MP_PASS_SCOPE) { EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg); } } } - if (comp->pass > PASS_1) { + if (comp->pass > MP_PASS_SCOPE) { bool success = EMIT_INLINE_ASM(end_pass); if (!success) { comp->had_error = true; @@ -3438,10 +3439,10 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is if (false) { #if MICROPY_EMIT_INLINE_THUMB } else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) { - compile_scope_inline_asm(comp, s, PASS_1); + compile_scope_inline_asm(comp, s, MP_PASS_SCOPE); #endif } else { - compile_scope(comp, s, PASS_1); + compile_scope(comp, s, MP_PASS_SCOPE); } // update maximim number of labels needed @@ -3482,9 +3483,9 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is comp->emit_method_table = NULL; comp->emit_inline_asm = emit_inline_thumb; comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table; - compile_scope_inline_asm(comp, s, PASS_2); + compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE); if (!comp->had_error) { - compile_scope_inline_asm(comp, s, PASS_3); + compile_scope_inline_asm(comp, s, MP_PASS_EMIT); } #endif @@ -3514,6 +3515,10 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is #endif comp->emit = emit_native; comp->emit_method_table->set_native_types(comp->emit, s->emit_options == MP_EMIT_OPT_VIPER); + + // native emitters need an extra pass to compute stack size + compile_scope(comp, s, MP_PASS_STACK_SIZE); + break; #endif // MICROPY_EMIT_NATIVE @@ -3527,10 +3532,14 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is } #endif // !MICROPY_EMIT_CPYTHON - // compile pass 2 and pass 3 - compile_scope(comp, s, PASS_2); + // second last pass: compute code size if (!comp->had_error) { - compile_scope(comp, s, PASS_3); + compile_scope(comp, s, MP_PASS_CODE_SIZE); + } + + // final pass: emit code + if (!comp->had_error) { + compile_scope(comp, s, MP_PASS_EMIT); } } } diff --git a/py/emit.h b/py/emit.h index ce7417d284..5a3b27d839 100644 --- a/py/emit.h +++ b/py/emit.h @@ -35,9 +35,10 @@ */ typedef enum { - PASS_1 = 1, // work out id's and their kind, and number of labels - PASS_2 = 2, // work out stack size and code size and label offsets - PASS_3 = 3, // emit code + MP_PASS_SCOPE = 1, // work out id's and their kind, and number of labels + MP_PASS_STACK_SIZE = 2, // work out maximum stack size + MP_PASS_CODE_SIZE = 3, // work out code size and label offsets + MP_PASS_EMIT = 4, // emit code } pass_kind_t; #define MP_EMIT_STAR_FLAG_SINGLE (0x01) diff --git a/py/emitbc.c b/py/emitbc.c index ce96d69828..6a8861eaef 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -83,7 +83,7 @@ void emit_bc_free(emit_t *emit) { // all functions must go through this one to emit code info STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_write) { //printf("emit %d\n", num_bytes_to_write); - if (emit->pass < PASS_3) { + if (emit->pass < MP_PASS_EMIT) { emit->code_info_offset += num_bytes_to_write; return emit->dummy_data; } else { @@ -123,7 +123,7 @@ STATIC void emit_write_code_info_bytes_lines(emit_t* emit, uint bytes_to_skip, u // all functions must go through this one to emit byte code STATIC byte* emit_get_cur_to_write_byte_code(emit_t* emit, int num_bytes_to_write) { //printf("emit %d\n", num_bytes_to_write); - if (emit->pass < PASS_3) { + if (emit->pass < MP_PASS_EMIT) { emit->byte_code_offset += num_bytes_to_write; return emit->dummy_data; } else { @@ -221,7 +221,7 @@ STATIC void emit_write_byte_code_byte_qstr(emit_t* emit, byte b, qstr qstr) { // unsigned labels are relative to ip following this instruction, stored as 16 bits STATIC void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, uint label) { uint byte_code_offset; - if (emit->pass < PASS_3) { + if (emit->pass < MP_PASS_EMIT) { byte_code_offset = 0; } else { byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3; @@ -235,7 +235,7 @@ STATIC void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, uint // signed labels are relative to ip following this instruction, stored as 16 bits, in excess STATIC void emit_write_byte_code_byte_signed_label(emit_t* emit, byte b1, uint label) { int byte_code_offset; - if (emit->pass < PASS_3) { + if (emit->pass < MP_PASS_EMIT) { byte_code_offset = 0; } else { byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3 + 0x8000; @@ -256,13 +256,13 @@ STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->scope = scope; emit->last_source_line_offset = 0; emit->last_source_line = 1; - if (pass == PASS_2) { + if (pass < MP_PASS_EMIT) { memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint)); } emit->byte_code_offset = 0; emit->code_info_offset = 0; - // write code info size (don't know size at this stage in PASS_2 so need to use maximum space (4 bytes) to write it) + // write code info size; use maximum space (4 bytes) to write it; TODO possible optimise this { byte* c = emit_get_cur_to_write_code_info(emit, 4); machine_uint_t s = emit->code_info_size; @@ -319,13 +319,13 @@ STATIC void emit_bc_end_pass(emit_t *emit) { *emit_get_cur_to_write_code_info(emit, 1) = 0; // end of line number info emit_align_code_info_to_machine_word(emit); // align so that following byte_code is aligned - if (emit->pass == PASS_2) { + if (emit->pass == MP_PASS_CODE_SIZE) { // calculate size of code in bytes emit->code_info_size = emit->code_info_offset; emit->byte_code_size = emit->byte_code_offset; emit->code_base = m_new0(byte, emit->code_info_size + emit->byte_code_size); - } else if (emit->pass == PASS_3) { + } else if (emit->pass == MP_PASS_EMIT) { qstr *arg_names = m_new(qstr, emit->scope->num_pos_args + emit->scope->num_kwonly_args); for (int i = 0; i < emit->scope->num_pos_args + emit->scope->num_kwonly_args; i++) { arg_names[i] = emit->scope->id_info[i].qstr; @@ -383,12 +383,12 @@ STATIC void emit_bc_pre(emit_t *emit, int stack_size_delta) { STATIC void emit_bc_label_assign(emit_t *emit, uint l) { emit_bc_pre(emit, 0); assert(l < emit->max_num_labels); - if (emit->pass == PASS_2) { + if (emit->pass < MP_PASS_EMIT) { // assign label offset assert(emit->label_offsets[l] == -1); emit->label_offsets[l] = emit->byte_code_offset; - } else if (emit->pass == PASS_3) { - // ensure label offset has not changed from PASS_2 to PASS_3 + } else { + // ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT //printf("l%d: (at %d vs %d)\n", l, emit->byte_code_offset, emit->label_offsets[l]); assert(emit->label_offsets[l] == emit->byte_code_offset); } @@ -827,17 +827,13 @@ STATIC void emit_bc_raise_varargs(emit_t *emit, int n_args) { STATIC void emit_bc_yield_value(emit_t *emit) { emit_bc_pre(emit, 0); - if (emit->pass == PASS_2) { - emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; - } + emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; emit_write_byte_code_byte(emit, MP_BC_YIELD_VALUE); } STATIC void emit_bc_yield_from(emit_t *emit) { emit_bc_pre(emit, -1); - if (emit->pass == PASS_2) { - emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; - } + emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; emit_write_byte_code_byte(emit, MP_BC_YIELD_FROM); } diff --git a/py/emitcpy.c b/py/emitcpy.c index cb2a0c1544..57b5ddd53d 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -72,7 +72,7 @@ STATIC void emit_cpy_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) emit->stack_size = 0; emit->last_emit_was_return_value = false; emit->scope = scope; - if (pass == PASS_2) { + if (pass < MP_PASS_EMIT) { memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(int)); } } @@ -114,7 +114,7 @@ static void emit_pre(emit_t *emit, int stack_size_delta, int byte_code_size) { emit->scope->stack_size = emit->stack_size; } emit->last_emit_was_return_value = false; - if (emit->pass == PASS_3 && byte_code_size > 0) { + if (emit->pass == MP_PASS_EMIT && byte_code_size > 0) { if (emit->byte_code_offset >= 1000) { printf("%d ", emit->byte_code_offset); } else { @@ -127,12 +127,12 @@ static void emit_pre(emit_t *emit, int stack_size_delta, int byte_code_size) { STATIC void emit_cpy_label_assign(emit_t *emit, uint l) { emit_pre(emit, 0, 0); assert(l < emit->max_num_labels); - if (emit->pass == PASS_2) { + if (emit->pass < PASS_EMIT) { // assign label offset assert(emit->label_offsets[l] == -1); emit->label_offsets[l] = emit->byte_code_offset; - } else if (emit->pass == PASS_3) { - // ensure label offset has not changed from PASS_2 to PASS_3 + } else { + // ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT assert(emit->label_offsets[l] == emit->byte_code_offset); //printf("l%d: (at %d)\n", l, emit->byte_code_offset); } @@ -140,28 +140,28 @@ STATIC void emit_cpy_label_assign(emit_t *emit, uint l) { STATIC void emit_cpy_import_name(emit_t *emit, qstr qstr) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("IMPORT_NAME %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_import_from(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("IMPORT_FROM %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_import_star(emit_t *emit) { emit_pre(emit, -1, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("IMPORT_STAR\n"); } } STATIC void emit_cpy_load_const_tok(emit_t *emit, mp_token_kind_t tok) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CONST "); switch (tok) { case MP_TOKEN_KW_FALSE: printf("False"); break; @@ -175,21 +175,21 @@ STATIC void emit_cpy_load_const_tok(emit_t *emit, mp_token_kind_t tok) { STATIC void emit_cpy_load_const_small_int(emit_t *emit, machine_int_t arg) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CONST " INT_FMT "\n", arg); } } STATIC void emit_cpy_load_const_int(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CONST %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_load_const_dec(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CONST %s\n", qstr_str(qstr)); } } @@ -233,7 +233,7 @@ STATIC void print_quoted_str(qstr qstr, bool bytes) { STATIC void emit_cpy_load_const_str(emit_t *emit, qstr qstr, bool bytes) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CONST "); print_quoted_str(qstr, bytes); printf("\n"); @@ -247,35 +247,35 @@ STATIC void emit_cpy_load_null(emit_t *emit) { STATIC void emit_cpy_load_fast(emit_t *emit, qstr qstr, uint id_flags, int local_num) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_FAST %d %s\n", local_num, qstr_str(qstr)); } } STATIC void emit_cpy_load_deref(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_DEREF %d %s\n", local_num, qstr_str(qstr)); } } STATIC void emit_cpy_load_name(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_NAME %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_load_global(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_GLOBAL %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_load_attr(emit_t *emit, qstr qstr) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_ATTR %s\n", qstr_str(qstr)); } } @@ -286,140 +286,140 @@ STATIC void emit_cpy_load_method(emit_t *emit, qstr qstr) { STATIC void emit_cpy_load_build_class(emit_t *emit) { emit_pre(emit, 1, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_BUILD_CLASS\n"); } } STATIC void emit_cpy_load_subscr(emit_t *emit) { emit_pre(emit, -1, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("BINARY_SUBSCR\n"); } } STATIC void emit_cpy_store_fast(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("STORE_FAST %d %s\n", local_num, qstr_str(qstr)); } } STATIC void emit_cpy_store_deref(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("STORE_DEREF %d %s\n", local_num, qstr_str(qstr)); } } STATIC void emit_cpy_store_name(emit_t *emit, qstr qstr) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("STORE_NAME %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_store_global(emit_t *emit, qstr qstr) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("STORE_GLOBAL %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_store_attr(emit_t *emit, qstr qstr) { emit_pre(emit, -2, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("STORE_ATTR %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_store_subscr(emit_t *emit) { emit_pre(emit, -3, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("STORE_SUBSCR\n"); } } STATIC void emit_cpy_delete_fast(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("DELETE_FAST %d %s\n", local_num, qstr_str(qstr)); } } STATIC void emit_cpy_delete_deref(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("DELETE_DEREF %d %s\n", local_num, qstr_str(qstr)); } } STATIC void emit_cpy_delete_name(emit_t *emit, qstr qstr) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("DELETE_NAME %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_delete_global(emit_t *emit, qstr qstr) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("DELETE_GLOBAL %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_delete_attr(emit_t *emit, qstr qstr) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("DELETE_ATTR %s\n", qstr_str(qstr)); } } STATIC void emit_cpy_delete_subscr(emit_t *emit) { emit_pre(emit, -2, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("DELETE_SUBSCR\n"); } } STATIC void emit_cpy_dup_top(emit_t *emit) { emit_pre(emit, 1, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("DUP_TOP\n"); } } STATIC void emit_cpy_dup_top_two(emit_t *emit) { emit_pre(emit, 2, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("DUP_TOP_TWO\n"); } } STATIC void emit_cpy_pop_top(emit_t *emit) { emit_pre(emit, -1, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("POP_TOP\n"); } } STATIC void emit_cpy_rot_two(emit_t *emit) { emit_pre(emit, 0, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("ROT_TWO\n"); } } STATIC void emit_cpy_rot_three(emit_t *emit) { emit_pre(emit, 0, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("ROT_THREE\n"); } } STATIC void emit_cpy_jump(emit_t *emit, uint label) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { int dest = emit->label_offsets[label]; if (dest < emit->byte_code_offset) { printf("JUMP_ABSOLUTE %d\n", emit->label_offsets[label]); @@ -431,35 +431,35 @@ STATIC void emit_cpy_jump(emit_t *emit, uint label) { STATIC void emit_cpy_pop_jump_if_true(emit_t *emit, uint label) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("POP_JUMP_IF_TRUE %d\n", emit->label_offsets[label]); } } STATIC void emit_cpy_pop_jump_if_false(emit_t *emit, uint label) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("POP_JUMP_IF_FALSE %d\n", emit->label_offsets[label]); } } STATIC void emit_cpy_jump_if_true_or_pop(emit_t *emit, uint label) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("JUMP_IF_TRUE_OR_POP %d\n", emit->label_offsets[label]); } } STATIC void emit_cpy_jump_if_false_or_pop(emit_t *emit, uint label) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("JUMP_IF_FALSE_OR_POP %d\n", emit->label_offsets[label]); } } STATIC void emit_cpy_break_loop(emit_t *emit, uint label, int except_depth) { emit_pre(emit, 0, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("BREAK_LOOP\n"); } } @@ -469,7 +469,7 @@ STATIC void emit_cpy_continue_loop(emit_t *emit, uint label, int except_depth) { emit_cpy_jump(emit, label); } else { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("CONTINUE_LOOP %d\n", emit->label_offsets[label]); } } @@ -477,49 +477,49 @@ STATIC void emit_cpy_continue_loop(emit_t *emit, uint label, int except_depth) { STATIC void emit_cpy_setup_with(emit_t *emit, uint label) { emit_pre(emit, 7, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("SETUP_WITH %d\n", emit->label_offsets[label]); } } STATIC void emit_cpy_with_cleanup(emit_t *emit) { emit_pre(emit, -7, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("WITH_CLEANUP\n"); } } STATIC void emit_cpy_setup_except(emit_t *emit, uint label) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("SETUP_EXCEPT %d\n", emit->label_offsets[label]); } } STATIC void emit_cpy_setup_finally(emit_t *emit, uint label) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("SETUP_FINALLY %d\n", emit->label_offsets[label]); } } STATIC void emit_cpy_end_finally(emit_t *emit) { emit_pre(emit, -1, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("END_FINALLY\n"); } } STATIC void emit_cpy_get_iter(emit_t *emit) { emit_pre(emit, 0, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("GET_ITER\n"); } } STATIC void emit_cpy_for_iter(emit_t *emit, uint label) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("FOR_ITER %d\n", emit->label_offsets[label]); } } @@ -530,21 +530,21 @@ STATIC void emit_cpy_for_iter_end(emit_t *emit) { STATIC void emit_cpy_pop_block(emit_t *emit) { emit_pre(emit, 0, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("POP_BLOCK\n"); } } STATIC void emit_cpy_pop_except(emit_t *emit) { emit_pre(emit, 0, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("POP_EXCEPT\n"); } } STATIC void emit_cpy_unary_op(emit_t *emit, mp_unary_op_t op) { emit_pre(emit, 0, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { switch (op) { case MP_UNARY_OP_POSITIVE: printf("UNARY_POSITIVE\n"); break; case MP_UNARY_OP_NEGATIVE: printf("UNARY_NEGATIVE\n"); break; @@ -563,7 +563,7 @@ STATIC void emit_cpy_binary_op(emit_t *emit, mp_binary_op_t op) { // CPython uses a byte code plus an argument for compare ops emit_pre(emit, -1, 3); } - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { switch (op) { case MP_BINARY_OP_OR: printf("BINARY_OR\n"); break; case MP_BINARY_OP_XOR: printf("BINARY_XOR\n"); break; @@ -607,77 +607,77 @@ STATIC void emit_cpy_binary_op(emit_t *emit, mp_binary_op_t op) { STATIC void emit_cpy_build_tuple(emit_t *emit, int n_args) { emit_pre(emit, 1 - n_args, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("BUILD_TUPLE %d\n", n_args); } } STATIC void emit_cpy_build_list(emit_t *emit, int n_args) { emit_pre(emit, 1 - n_args, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("BUILD_LIST %d\n", n_args); } } STATIC void emit_cpy_list_append(emit_t *emit, int list_index) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LIST_APPEND %d\n", list_index); } } STATIC void emit_cpy_build_map(emit_t *emit, int n_args) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("BUILD_MAP %d\n", n_args); } } STATIC void emit_cpy_store_map(emit_t *emit) { emit_pre(emit, -2, 1); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("STORE_MAP\n"); } } STATIC void emit_cpy_map_add(emit_t *emit, int map_index) { emit_pre(emit, -2, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("MAP_ADD %d\n", map_index); } } STATIC void emit_cpy_build_set(emit_t *emit, int n_args) { emit_pre(emit, 1 - n_args, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("BUILD_SET %d\n", n_args); } } STATIC void emit_cpy_set_add(emit_t *emit, int set_index) { emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("SET_ADD %d\n", set_index); } } STATIC void emit_cpy_build_slice(emit_t *emit, int n_args) { emit_pre(emit, 1 - n_args, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("BUILD_SLICE %d\n", n_args); } } STATIC void emit_cpy_unpack_sequence(emit_t *emit, int n_args) { emit_pre(emit, -1 + n_args, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("UNPACK_SEQUENCE %d\n", n_args); } } STATIC void emit_cpy_unpack_ex(emit_t *emit, int n_left, int n_right) { emit_pre(emit, -1 + n_left + n_right + 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("UNPACK_EX %d\n", n_left | (n_right << 8)); } } @@ -691,7 +691,7 @@ STATIC void emit_cpy_call_function(emit_t *emit, int n_positional, int n_keyword s += 1; } emit_pre(emit, -n_positional - 2 * n_keyword - s, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { if (star_flags & MP_EMIT_STAR_FLAG_SINGLE) { if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) { printf("CALL_FUNCTION_VAR_KW"); @@ -716,26 +716,26 @@ STATIC void emit_cpy_call_method(emit_t *emit, int n_positional, int n_keyword, STATIC void emit_cpy_return_value(emit_t *emit) { emit_pre(emit, -1, 1); emit->last_emit_was_return_value = true; - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("RETURN_VALUE\n"); } } STATIC void emit_cpy_raise_varargs(emit_t *emit, int n_args) { emit_pre(emit, -n_args, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("RAISE_VARARGS %d\n", n_args); } } STATIC void load_cpy_const_code_and_name(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CONST code %s\n", qstr_str(qstr)); } // load qualified name emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CONST '"); // code just to work out the qualname (or whatever it is) { @@ -762,7 +762,7 @@ STATIC void load_cpy_const_code_and_name(emit_t *emit, qstr qstr) { STATIC void emit_cpy_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) { load_cpy_const_code_and_name(emit, scope->simple_name); emit_pre(emit, -1 - n_pos_defaults - 2 * n_kw_defaults, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("MAKE_FUNCTION %d\n", (n_kw_defaults << 8) | n_pos_defaults); } } @@ -771,48 +771,44 @@ STATIC void emit_cpy_make_closure(emit_t *emit, scope_t *scope, uint n_closed_ov emit_cpy_build_tuple(emit, n_closed_over); load_cpy_const_code_and_name(emit, scope->simple_name); emit_pre(emit, -2 - n_pos_defaults - 2 * n_kw_defaults, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("MAKE_CLOSURE %d\n", (n_kw_defaults << 8) | n_pos_defaults); } } STATIC void emit_cpy_yield_value(emit_t *emit) { emit_pre(emit, 0, 1); - if (emit->pass == PASS_2) { - emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; - } - if (emit->pass == PASS_3) { + emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; + if (emit->pass == MP_PASS_EMIT) { printf("YIELD_VALUE\n"); } } STATIC void emit_cpy_yield_from(emit_t *emit) { emit_pre(emit, -1, 1); - if (emit->pass == PASS_2) { - emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; - } - if (emit->pass == PASS_3) { + emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; + if (emit->pass == MP_PASS_EMIT) { printf("YIELD_FROM\n"); } } STATIC void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CONST %s\n", str); } } STATIC void emit_cpy_load_closure(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("LOAD_CLOSURE %d %s\n", local_num, qstr_str(qstr)); } } STATIC void emit_cpy_setup_loop(emit_t *emit, uint label) { emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { printf("SETUP_LOOP %d\n", emit->label_offsets[label]); } } diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index ecdee3429d..83ee7f69bf 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -89,7 +89,7 @@ STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pa emit->pass = pass; emit->success = true; emit->scope = scope; - asm_thumb_start_pass(emit->as, pass); + asm_thumb_start_pass(emit->as, pass == MP_PASS_EMIT ? ASM_THUMB_PASS_EMIT : ASM_THUMB_PASS_COMPUTE); asm_thumb_entry(emit->as, 0); } @@ -97,7 +97,7 @@ STATIC bool emit_inline_thumb_end_pass(emit_inline_asm_t *emit) { asm_thumb_exit(emit->as); asm_thumb_end_pass(emit->as); - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { void *f = asm_thumb_get_code(emit->as); mp_emit_glue_assign_inline_asm_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_pos_args); } @@ -230,7 +230,7 @@ STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_ } } // only need to have the labels on the last pass - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { emit_inline_thumb_error(emit, "label '%s' not defined\n", qstr_str(label_qstr)); } return 0; diff --git a/py/emitnative.c b/py/emitnative.c index bf21f66f58..4ef9e5a7a3 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -86,6 +86,7 @@ #define REG_TEMP2 (REG_RSI) #define ASM_MOV_REG_TO_LOCAL(reg, local_num) asm_x64_mov_r64_to_local(emit->as, (reg), (local_num)) #define ASM_MOV_IMM_TO_REG(imm, reg) asm_x64_mov_i64_to_r64_optimised(emit->as, (imm), (reg)) +#define ASM_MOV_ALIGNED_IMM_TO_REG(imm, reg) asm_x64_mov_i64_to_r64_aligned(emit->as, (imm), (reg)) #define ASM_MOV_IMM_TO_LOCAL_USING(imm, local_num, reg_temp) do { asm_x64_mov_i64_to_r64_optimised(emit->as, (imm), (reg_temp)); asm_x64_mov_r64_to_local(emit->as, (reg_temp), (local_num)); } while (false) #define ASM_MOV_LOCAL_TO_REG(local_num, reg) asm_x64_mov_local_to_r64(emit->as, (local_num), (reg)) #define ASM_MOV_REG_TO_REG(reg_src, reg_dest) asm_x64_mov_r64_to_r64(emit->as, (reg_src), (reg_dest)) @@ -109,6 +110,7 @@ #define REG_TEMP2 (REG_R2) #define ASM_MOV_REG_TO_LOCAL(reg, local_num) asm_thumb_mov_local_reg(emit->as, (local_num), (reg)) #define ASM_MOV_IMM_TO_REG(imm, reg) asm_thumb_mov_reg_i32_optimised(emit->as, (reg), (imm)) +#define ASM_MOV_ALIGNED_IMM_TO_REG(imm, reg) asm_thumb_mov_reg_i32_aligned(emit->as, (reg), (imm)) #define ASM_MOV_IMM_TO_LOCAL_USING(imm, local_num, reg_temp) do { asm_thumb_mov_reg_i32_optimised(emit->as, (reg_temp), (imm)); asm_thumb_mov_local_reg(emit->as, (local_num), (reg_temp)); } while (false) #define ASM_MOV_LOCAL_TO_REG(local_num, reg) asm_thumb_mov_reg_local(emit->as, (reg), (local_num)) #define ASM_MOV_REG_TO_REG(reg_src, reg_dest) asm_thumb_mov_reg_reg(emit->as, (reg_dest), (reg_src)) @@ -146,10 +148,10 @@ struct _emit_t { bool do_viper_types; - int local_vtype_alloc; + uint local_vtype_alloc; vtype_kind_t *local_vtype; - int stack_info_alloc; + uint stack_info_alloc; stack_info_t *stack_info; int stack_start; @@ -167,10 +169,7 @@ struct _emit_t { }; emit_t *EXPORT_FUN(new)(uint max_num_labels) { - emit_t *emit = m_new(emit_t, 1); - emit->do_viper_types = false; - emit->local_vtype = NULL; - emit->stack_info = NULL; + emit_t *emit = m_new0(emit_t, 1); #if N_X64 emit->as = asm_x64_new(max_num_labels); #elif N_THUMB @@ -185,6 +184,8 @@ void EXPORT_FUN(free)(emit_t *emit) { #elif N_THUMB asm_thumb_free(emit->as, false); #endif + m_del(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc); + m_del(stack_info_t, emit->stack_info, emit->stack_info_alloc); m_del_obj(emit_t, emit); } @@ -199,12 +200,16 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->last_emit_was_return_value = false; emit->scope = scope; - if (emit->local_vtype == NULL) { - emit->local_vtype_alloc = scope->num_locals + 20; // XXX should be maximum over all scopes - emit->local_vtype = m_new(vtype_kind_t, emit->local_vtype_alloc); + // allocate memory for keeping track of the types of locals + if (emit->local_vtype_alloc < scope->num_locals) { + emit->local_vtype = m_renew(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc, scope->num_locals); + emit->local_vtype_alloc = scope->num_locals; } + + // allocate memory for keeping track of the objects on the stack + // XXX don't know stack size on entry, and it should be maximum over all scopes if (emit->stack_info == NULL) { - emit->stack_info_alloc = scope->stack_size + 50; // XXX don't know stack size on entry, should be maximum over all scopes + emit->stack_info_alloc = scope->stack_size + 50; emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc); } @@ -228,14 +233,14 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop } #if N_X64 - asm_x64_start_pass(emit->as, pass); + asm_x64_start_pass(emit->as, pass == MP_PASS_EMIT ? ASM_X64_PASS_EMIT : ASM_X64_PASS_COMPUTE); #elif N_THUMB - asm_thumb_start_pass(emit->as, pass); + asm_thumb_start_pass(emit->as, pass == MP_PASS_EMIT ? ASM_THUMB_PASS_EMIT : ASM_THUMB_PASS_COMPUTE); #endif // entry to function int num_locals = 0; - if (pass > PASS_1) { + if (pass > MP_PASS_SCOPE) { num_locals = scope->num_locals - REG_LOCAL_NUM; if (num_locals < 0) { num_locals = 0; @@ -243,11 +248,6 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->stack_start = num_locals; num_locals += scope->stack_size; } - if (pass == PASS_2) { - // XXX big hack to make sure we have some locals in PASS_2 - // this is so that on PASS_2 the code emitted in x64 has the right size - num_locals += 2; - } #if N_X64 asm_x64_entry(emit->as, num_locals); #elif N_THUMB @@ -306,7 +306,7 @@ STATIC void emit_native_end_pass(emit_t *emit) { printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size); } - if (emit->pass == PASS_3) { + if (emit->pass == MP_PASS_EMIT) { #if N_X64 void *f = asm_x64_get_code(emit->as); mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_x64_get_code_size(emit->as), emit->scope->num_pos_args); @@ -332,7 +332,7 @@ STATIC void adjust_stack(emit_t *emit, int stack_size_delta) { DEBUG_printf("adjust stack: stack:%d + delta:%d\n", emit->stack_size, stack_size_delta); assert((int)emit->stack_size + stack_size_delta >= 0); emit->stack_size += stack_size_delta; - if (emit->pass > PASS_1 && emit->stack_size > emit->scope->stack_size) { + if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) { emit->scope->stack_size = emit->stack_size; } } @@ -572,9 +572,10 @@ STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void #endif } -STATIC void emit_call_with_3_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val1, int arg_reg1, machine_int_t arg_val2, int arg_reg2, machine_int_t arg_val3, int arg_reg3) { +// the first arg is stored in the code aligned on a machine_uint_t boundary +STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val1, int arg_reg1, machine_int_t arg_val2, int arg_reg2, machine_int_t arg_val3, int arg_reg3) { need_reg_all(emit); - ASM_MOV_IMM_TO_REG(arg_val1, arg_reg1); + ASM_MOV_ALIGNED_IMM_TO_REG(arg_val1, arg_reg1); ASM_MOV_IMM_TO_REG(arg_val2, arg_reg2); ASM_MOV_IMM_TO_REG(arg_val3, arg_reg3); #if N_X64 @@ -1209,9 +1210,7 @@ STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_d // call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them assert(n_pos_defaults == 0 && n_kw_defaults == 0); emit_native_pre(emit); - assert(0); - // TODO we need to store the raw_code ptr aligned within the code for the GC - emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); + emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } diff --git a/py/emitpass1.c b/py/emitpass1.c index 48b9aa69e9..2e76420a21 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -56,7 +56,7 @@ STATIC void emit_pass1_dummy(emit_t *emit) { } STATIC void emit_pass1_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { - assert(pass == PASS_1); + assert(pass == MP_PASS_SCOPE); emit->scope = scope; } diff --git a/py/runtime.c b/py/runtime.c index 5ac012e3de..fd5752fbed 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1156,12 +1156,12 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_call_function_n_kw_for_native, mp_call_method_n_kw, mp_getiter, + mp_iternext, mp_import_name, mp_import_from, mp_import_all, mp_obj_new_slice, mp_unpack_sequence, - mp_iternext, }; /*