Skip to content

Commit b6e6b52

Browse files
committed
py: Implement proper re-raising in native codegen's finally handler.
This allows an exception to propagate correctly through a finally handler.
1 parent 962a5d5 commit b6e6b52

4 files changed

Lines changed: 15 additions & 5 deletions

File tree

py/emitnative.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1824,7 +1824,14 @@ STATIC void emit_native_setup_finally(emit_t *emit, mp_uint_t label) {
18241824
}
18251825

18261826
STATIC void emit_native_end_finally(emit_t *emit) {
1827-
emit_pre_pop_discard(emit);
1827+
// logic:
1828+
// exc = pop_stack
1829+
// if exc == None: pass
1830+
// else: raise exc
1831+
// the check if exc is None is done in the MP_F_NATIVE_RAISE stub
1832+
vtype_kind_t vtype;
1833+
emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
1834+
emit_call(emit, MP_F_NATIVE_RAISE);
18281835
emit_post(emit);
18291836
}
18301837

py/nativeglue.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,11 @@ mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, cons
8080
}
8181

8282
// wrapper that makes raise obj and raises it
83-
NORETURN void mp_native_raise(mp_obj_t o) {
84-
nlr_raise(mp_make_raise_obj(o));
83+
// END_FINALLY opcode requires that we don't raise if o==None
84+
void mp_native_raise(mp_obj_t o) {
85+
if (o != mp_const_none) {
86+
nlr_raise(mp_make_raise_obj(o));
87+
}
8588
}
8689

8790
// these must correspond to the respective enum in runtime0.h

py/runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ NORETURN void mp_not_implemented(const char *msg);
119119
mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type);
120120
mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type);
121121
mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, const mp_obj_t *args);
122-
NORETURN void mp_native_raise(mp_obj_t o);
122+
void mp_native_raise(mp_obj_t o);
123123

124124
extern struct _mp_obj_list_t mp_sys_path_obj;
125125
extern struct _mp_obj_list_t mp_sys_argv_obj;

tests/run-tests

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def run_tests(pyb, tests, args):
7878
# Some tests are known to fail with native emitter
7979
# Remove them from the below when they work
8080
if args.emit == 'native':
81-
skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class class_super class_super_object closure1 closure2 closure_defargs del_deref del_local fun3 fun_calldblstar fun_callstar fun_callstardblstar fun_defargs fun_defargs2 fun_kwargs fun_kwonly fun_kwonlydef fun_kwvarargs fun_varargs gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_throw generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send globals_del string_format string_join subclass_native2_list subclass_native2_tuple try2 try_finally1 try_finally_loops try_finally_return try_reraise try_reraise2 unboundlocal with1 with_break with_continue with_return'.split()})
81+
skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class class_super class_super_object closure1 closure2 closure_defargs del_deref del_local fun3 fun_calldblstar fun_callstar fun_callstardblstar fun_defargs fun_defargs2 fun_kwargs fun_kwonly fun_kwonlydef fun_kwvarargs fun_varargs gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_throw generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send globals_del string_format string_join subclass_native2_list subclass_native2_tuple try_finally_loops try_finally_return try_reraise try_reraise2 unboundlocal with1 with_break with_continue with_return'.split()})
8282
skip_tests.add('float/string_format.py')
8383
skip_tests.add('import/gen_context.py')
8484
skip_tests.add('io/file_with.py')

0 commit comments

Comments
 (0)