py, compiler: Improve passes; add an extra pass for native emitter.

pull/584/head
Damien George 2014-05-07 17:24:22 +01:00
rodzic ca25c15d56
commit 36db6bcf54
12 zmienionych plików z 216 dodań i 201 usunięć

Wyświetl plik

@ -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));
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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);
}
}
}

Wyświetl plik

@ -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)

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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]);
}
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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,
};
/*