summaryrefslogtreecommitdiff
path: root/py/emitbc.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/emitbc.c')
-rw-r--r--py/emitbc.c22
1 files changed, 22 insertions, 0 deletions
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) {