diff options
Diffstat (limited to 'py')
| -rw-r--r-- | py/asmbase.c | 10 | ||||
| -rw-r--r-- | py/asmbase.h | 11 | ||||
| -rw-r--r-- | py/emitbc.c | 22 | ||||
| -rw-r--r-- | py/emitnative.c | 2 |
4 files changed, 44 insertions, 1 deletions
diff --git a/py/asmbase.c b/py/asmbase.c index 4a3fd089c..da4273506 100644 --- a/py/asmbase.c +++ b/py/asmbase.c @@ -55,15 +55,20 @@ void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) { assert(as->code_base != NULL); } as->pass = pass; + as->suppress = false; as->code_offset = 0; } // all functions must go through this one to emit bytes // if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number // of bytes needed and returns NULL, and callers should not store any data +// It also returns NULL if generated code should be suppressed at this point. uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_write) { mp_asm_base_t *as = as_in; uint8_t *c = NULL; + if (as->suppress) { + return c; + } if (as->pass == MP_ASM_PASS_EMIT) { assert(as->code_offset + num_bytes_to_write <= as->code_size); c = as->code_base + as->code_offset; @@ -74,6 +79,11 @@ uint8_t *mp_asm_base_get_cur_to_write_bytes(void *as_in, size_t num_bytes_to_wri void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) { assert(label < as->max_num_labels); + + // Assiging a label ends any dead-code region, and all following machine + // code should be emitted (until another mp_asm_base_suppress_code() call). + as->suppress = false; + if (as->pass < MP_ASM_PASS_EMIT) { // assign label offset assert(as->label_offsets[label] == (size_t)-1); diff --git a/py/asmbase.h b/py/asmbase.h index 960be7685..352d2f54c 100644 --- a/py/asmbase.h +++ b/py/asmbase.h @@ -33,7 +33,12 @@ #define MP_ASM_PASS_EMIT (2) typedef struct _mp_asm_base_t { - int pass; + uint8_t pass; + + // Set to true using mp_asm_base_suppress_code() if the code generator + // should suppress emitted code due to it being dead code. + bool suppress; + size_t code_offset; size_t code_size; uint8_t *code_base; @@ -50,6 +55,10 @@ void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label); void mp_asm_base_align(mp_asm_base_t *as, unsigned int align); void mp_asm_base_data(mp_asm_base_t *as, unsigned int bytesize, uintptr_t val); +static inline void mp_asm_base_suppress_code(mp_asm_base_t *as) { + as->suppress = true; +} + static inline size_t mp_asm_base_get_code_pos(mp_asm_base_t *as) { return as->code_offset; } diff --git a/py/emitbc.c b/py/emitbc.c index 9c0d78d79..70a4d8b12 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -48,6 +48,11 @@ struct _emit_t { pass_kind_t pass : 8; + // Set to true if the code generator should suppress emitted code due to it + // being dead code. This can happen when opcodes immediately follow an + // unconditional flow control (eg jump or raise). + bool suppress; + int stack_size; mp_emit_common_t *emit_common; @@ -140,6 +145,9 @@ STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_sk // all functions must go through this one to emit byte code STATIC uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_to_write) { emit_t *emit = emit_in; + if (emit->suppress) { + return emit->dummy_data; + } if (emit->pass < MP_PASS_EMIT) { emit->bytecode_offset += num_bytes_to_write; return emit->dummy_data; @@ -222,6 +230,10 @@ STATIC void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b, STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { mp_emit_bc_adjust_stack_size(emit, stack_adj); + if (emit->suppress) { + return; + } + // Determine if the jump offset is signed or unsigned, based on the opcode. const bool is_signed = b1 <= MP_BC_POP_JUMP_IF_FALSE; @@ -271,6 +283,7 @@ STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->pass = pass; emit->stack_size = 0; + emit->suppress = false; emit->scope = scope; emit->last_source_line_offset = 0; emit->last_source_line = 1; @@ -426,6 +439,10 @@ void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { } void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) { + // Assiging a label ends any dead-code region, and all following opcodes + // should be emitted (until another unconditional flow control). + emit->suppress = false; + mp_emit_bc_adjust_stack_size(emit, 0); if (emit->pass == MP_PASS_SCOPE) { return; @@ -589,6 +606,7 @@ void mp_emit_bc_rot_three(emit_t *emit) { void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) { emit_write_bytecode_byte_label(emit, 0, MP_BC_JUMP, label); + emit->suppress = true; } void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) { @@ -622,6 +640,7 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept emit_write_bytecode_byte_label(emit, 0, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); emit_write_bytecode_raw_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth); } + emit->suppress = true; } void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) { @@ -663,6 +682,7 @@ void mp_emit_bc_for_iter_end(emit_t *emit) { void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { (void)within_exc_handler; emit_write_bytecode_byte_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label); + emit->suppress = true; } void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) { @@ -766,6 +786,7 @@ void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_ke void mp_emit_bc_return_value(emit_t *emit) { emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE); + emit->suppress = true; } void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { @@ -773,6 +794,7 @@ void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 2 == MP_BC_RAISE_FROM); assert(n_args <= 2); emit_write_bytecode_byte(emit, -n_args, MP_BC_RAISE_LAST + n_args); + emit->suppress = true; } void mp_emit_bc_yield(emit_t *emit, int kind) { diff --git a/py/emitnative.c b/py/emitnative.c index 5b695a22a..957e713fd 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1966,6 +1966,7 @@ STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) { need_stack_settled(emit); ASM_JUMP(emit->as, label); emit_post(emit); + mp_asm_base_suppress_code(&emit->as->base); } STATIC void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bool pop) { @@ -2810,6 +2811,7 @@ STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { } // TODO probably make this 1 call to the runtime (which could even call convert, native_raise(obj, type)) emit_call(emit, MP_F_NATIVE_RAISE); + mp_asm_base_suppress_code(&emit->as->base); } STATIC void emit_native_yield(emit_t *emit, int kind) { |
