summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/asmbase.c10
-rw-r--r--py/asmbase.h11
-rw-r--r--py/emitbc.c22
-rw-r--r--py/emitnative.c2
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) {