Skip to content

Commit 2b5669d

Browse files
committed
py/emitnative: Generate shorter RV32 code for exception handling.
This commit lets the native emitter generate shorter code when clearing exception objects on RV32. Since there are no direct generic ASM functions to set a specific immediate to a local variable, the native emitter usually generates an immediate assignment to a temporary register and then a store of that register into the chosen local variable. This pattern is also followed when clearing certain local variables related to exception handling, using MP_OBJ_NULL as the immediate value to set. Given that at the moment MP_OBJ_NULL is defined to be 0 (with some other spots in the native emitter that leverage that fact when checking the state of the variables mentioned earlier), and that the RV32 CPU has a dedicated register that is hardwired to read 0, a new method to set local variables to MP_OBJ_NULL is introduced. When generating RV32 code, the new macro will skip the intermediate register assignment and directly uses the X0/ZERO register to set the chosen local variable to MP_OBJ_NULL. Other platforms will still generate the same code sequence as before this change. This is a followup to 40585ea. Signed-off-by: Alessandro Gatti <[email protected]>
1 parent e0a9b70 commit 2b5669d

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

py/emitnative.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,27 @@ struct _emit_t {
287287
#define ASM_CLR_REG(state, rd) ASM_XOR_REG_REG(state, rd, rd)
288288
#endif
289289

290+
#if N_RV32
291+
#define ASM_MOV_LOCAL_MP_OBJ_NULL(as, local_num, reg_temp) \
292+
ASM_MOV_LOCAL_REG(as, local_num, REG_ZERO)
293+
#else
294+
#define ASM_MOV_LOCAL_MP_OBJ_NULL(as, local_num, reg_temp) \
295+
ASM_MOV_REG_IMM(as, reg_temp, (mp_uint_t)MP_OBJ_NULL); \
296+
ASM_MOV_LOCAL_REG(as, local_num, reg_temp)
297+
#endif
298+
290299
static void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj);
291300
static void emit_native_global_exc_entry(emit_t *emit);
292301
static void emit_native_global_exc_exit(emit_t *emit);
293302
static void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj);
294303

295304
emit_t *EXPORT_FUN(new)(mp_emit_common_t * emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels) {
305+
// Generated code performing exception handling assumes that MP_OBJ_NULL
306+
// equals to 0 to simplify some checks, leveraging dedicated opcodes for
307+
// comparisons against 0. If this assumption does not hold true anymore
308+
// then generated code won't work correctly.
309+
MP_STATIC_ASSERT(MP_OBJ_NULL == 0);
310+
296311
emit_t *emit = m_new0(emit_t, 1);
297312
emit->emit_common = emit_common;
298313
emit->error_slot = error_slot;
@@ -1291,8 +1306,7 @@ static void emit_native_global_exc_entry(emit_t *emit) {
12911306

12921307
// Check LOCAL_IDX_THROW_VAL for any injected value
12931308
ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_THROW_VAL(emit));
1294-
ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL);
1295-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2);
1309+
ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2);
12961310
emit_call(emit, MP_F_NATIVE_RAISE);
12971311
}
12981312
}
@@ -2208,8 +2222,7 @@ static void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) {
22082222

22092223
// Replace exception with MP_OBJ_NULL.
22102224
emit_native_label_assign(emit, *emit->label_slot);
2211-
ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL);
2212-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
2225+
ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
22132226

22142227
// end of with cleanup nlr_catch block
22152228
emit_native_label_assign(emit, *emit->label_slot + 1);
@@ -2316,8 +2329,7 @@ static void emit_native_for_iter_end(emit_t *emit) {
23162329
static void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
23172330
if (within_exc_handler) {
23182331
// Cancel any active exception so subsequent handlers don't see it
2319-
ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL);
2320-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
2332+
ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
23212333
} else {
23222334
emit_native_leave_exc_stack(emit, false);
23232335
}
@@ -3002,8 +3014,7 @@ static void emit_native_yield(emit_t *emit, int kind) {
30023014
if (kind == MP_EMIT_YIELD_VALUE) {
30033015
// Check LOCAL_IDX_THROW_VAL for any injected value
30043016
ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_THROW_VAL(emit));
3005-
ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL);
3006-
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2);
3017+
ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2);
30073018
emit_call(emit, MP_F_NATIVE_RAISE);
30083019
} else {
30093020
// Label loop entry

0 commit comments

Comments
 (0)