diff --git a/py/compile.c b/py/compile.c index 6dc39b1dcc..45217cfe99 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3764,22 +3764,22 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is case MP_EMIT_OPT_VIPER: #if MICROPY_EMIT_X64 if (emit_native == NULL) { - emit_native = emit_native_x64_new(max_num_labels); + emit_native = emit_native_x64_new(&comp->compile_error, max_num_labels); } comp->emit_method_table = &emit_native_x64_method_table; #elif MICROPY_EMIT_X86 if (emit_native == NULL) { - emit_native = emit_native_x86_new(max_num_labels); + emit_native = emit_native_x86_new(&comp->compile_error, max_num_labels); } comp->emit_method_table = &emit_native_x86_method_table; #elif MICROPY_EMIT_THUMB if (emit_native == NULL) { - emit_native = emit_native_thumb_new(max_num_labels); + emit_native = emit_native_thumb_new(&comp->compile_error, max_num_labels); } comp->emit_method_table = &emit_native_thumb_method_table; #elif MICROPY_EMIT_ARM if (emit_native == NULL) { - emit_native = emit_native_arm_new(max_num_labels); + emit_native = emit_native_arm_new(&comp->compile_error, max_num_labels); } comp->emit_method_table = &emit_native_arm_method_table; #endif diff --git a/py/emit.h b/py/emit.h index 268c9d66ca..35ba08db9e 100644 --- a/py/emit.h +++ b/py/emit.h @@ -172,10 +172,10 @@ extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops emit_t *emit_cpython_new(void); emit_t *emit_bc_new(void); -emit_t *emit_native_x64_new(mp_uint_t max_num_labels); -emit_t *emit_native_x86_new(mp_uint_t max_num_labels); -emit_t *emit_native_thumb_new(mp_uint_t max_num_labels); -emit_t *emit_native_arm_new(mp_uint_t max_num_labels); +emit_t *emit_native_x64_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); +emit_t *emit_native_x86_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); +emit_t *emit_native_thumb_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); +emit_t *emit_native_arm_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); void emit_cpython_set_max_num_labels(emit_t* emit, mp_uint_t max_num_labels); void emit_bc_set_max_num_labels(emit_t* emit, mp_uint_t max_num_labels); diff --git a/py/emitnative.c b/py/emitnative.c index 0b13476766..126596b464 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -482,6 +482,10 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { #endif +#define EMIT_NATIVE_VIPER_TYPE_ERROR(emit, ...) do { \ + *emit->error_slot = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, __VA_ARGS__); \ + } while (0) + typedef enum { STACK_VALUE, STACK_REG, @@ -505,6 +509,19 @@ typedef enum { VTYPE_BUILTIN_CAST = 0x60 | MP_NATIVE_TYPE_OBJ, } vtype_kind_t; +STATIC qstr vtype_to_qstr(vtype_kind_t vtype) { + switch (vtype) { + case VTYPE_PYOBJ: return MP_QSTR_object; + case VTYPE_BOOL: return MP_QSTR_bool; + case VTYPE_INT: return MP_QSTR_int; + case VTYPE_UINT: return MP_QSTR_uint; + case VTYPE_PTR: return MP_QSTR_ptr; + case VTYPE_PTR8: return MP_QSTR_ptr8; + case VTYPE_PTR16: return MP_QSTR_ptr16; + case VTYPE_PTR_NONE: default: return MP_QSTR_None; + } +} + typedef struct _stack_info_t { vtype_kind_t vtype; stack_info_kind_t kind; @@ -515,6 +532,7 @@ typedef struct _stack_info_t { } stack_info_t; struct _emit_t { + mp_obj_t *error_slot; int pass; bool do_viper_types; @@ -542,8 +560,9 @@ struct _emit_t { ASM_T *as; }; -emit_t *EXPORT_FUN(new)(mp_uint_t max_num_labels) { +emit_t *EXPORT_FUN(new)(mp_obj_t *error_slot, mp_uint_t max_num_labels) { emit_t *emit = m_new0(emit_t, 1); + emit->error_slot = error_slot; emit->as = ASM_NEW(max_num_labels); return emit; } @@ -571,7 +590,7 @@ STATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t ar case MP_QSTR_ptr: type = VTYPE_PTR; break; case MP_QSTR_ptr8: type = VTYPE_PTR8; break; case MP_QSTR_ptr16: type = VTYPE_PTR16; break; - default: mp_printf(&mp_plat_print, "ViperTypeError: unknown type %q\n", arg2); return; + default: EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "unknown type '%q'", arg2); return; } if (op == MP_EMIT_NATIVE_TYPE_RETURN) { emit->return_vtype = type; @@ -1288,7 +1307,7 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { DEBUG_printf("load_fast(%s, " UINT_FMT ")\n", qstr_str(qst), local_num); vtype_kind_t vtype = emit->local_vtype[local_num]; if (vtype == VTYPE_UNBOUND) { - mp_printf(&mp_plat_print, "ViperTypeError: local %q used before type known\n", qst); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "local '%q' used before type known", qst); } emit_native_pre(emit); if (local_num == 0) { @@ -1438,7 +1457,8 @@ STATIC void emit_native_load_subscr(emit_t *emit) { break; } default: - mp_printf(&mp_plat_print, "ViperTypeError: can't load from type %d\n", vtype_base); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "can't load from '%q'", vtype_to_qstr(vtype_base)); } } else { // index is not an immediate @@ -1464,7 +1484,8 @@ STATIC void emit_native_load_subscr(emit_t *emit) { break; } default: - mp_printf(&mp_plat_print, "ViperTypeError: can't load from type %d\n", vtype_base); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "can't load from '%q'", vtype_to_qstr(vtype_base)); } } emit_post_push_reg(emit, VTYPE_INT, REG_RET); @@ -1495,7 +1516,9 @@ STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) emit->local_vtype[local_num] = vtype; } else if (emit->local_vtype[local_num] != vtype) { // type of local is not the same as object stored in it - mp_printf(&mp_plat_print, "ViperTypeError: type mismatch, local %q has type %d but source object has type %d\n", qst, emit->local_vtype[local_num], vtype); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "local '%q' has type '%q' but source is '%q'", + qst, vtype_to_qstr(emit->local_vtype[local_num]), vtype_to_qstr(vtype)); } } @@ -1625,7 +1648,8 @@ STATIC void emit_native_store_subscr(emit_t *emit) { break; } default: - mp_printf(&mp_plat_print, "ViperTypeError: can't store to type %d\n", vtype_base); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "can't store to '%q'", vtype_to_qstr(vtype_base)); } } else { // index is not an immediate @@ -1666,7 +1690,8 @@ STATIC void emit_native_store_subscr(emit_t *emit) { break; } default: - mp_printf(&mp_plat_print, "ViperTypeError: can't store to type %d\n", vtype_base); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "can't store to '%q'", vtype_to_qstr(vtype_base)); } } @@ -1761,25 +1786,21 @@ STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) { STATIC void emit_native_jump_helper(emit_t *emit, bool pop) { vtype_kind_t vtype = peek_vtype(emit, 0); - switch (vtype) { - case VTYPE_PYOBJ: - emit_pre_pop_reg(emit, &vtype, REG_ARG_1); - if (!pop) { - adjust_stack(emit, 1); - } - emit_call(emit, MP_F_OBJ_IS_TRUE); - break; - case VTYPE_BOOL: - case VTYPE_INT: - case VTYPE_UINT: - emit_pre_pop_reg(emit, &vtype, REG_RET); - if (!pop) { - adjust_stack(emit, 1); - } - break; - default: - mp_printf(&mp_plat_print, "ViperTypeError: expecting a bool or pyobj, got %d\n", vtype); - assert(0); + if (vtype == VTYPE_PYOBJ) { + emit_pre_pop_reg(emit, &vtype, REG_ARG_1); + if (!pop) { + adjust_stack(emit, 1); + } + emit_call(emit, MP_F_OBJ_IS_TRUE); + } else { + emit_pre_pop_reg(emit, &vtype, REG_RET); + if (!pop) { + adjust_stack(emit, 1); + } + if (!(vtype == VTYPE_BOOL || vtype == VTYPE_INT || vtype == VTYPE_UINT)) { + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "can't implicitly convert '%q' to 'bool'", vtype_to_qstr(vtype)); + } } // For non-pop need to save the vtype so that emit_native_adjust_stack_size // can use it. This is a bit of a hack. @@ -2056,7 +2077,9 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { } emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { - mp_printf(&mp_plat_print, "ViperTypeError: can't do binary op between types %d and %d\n", vtype_lhs, vtype_rhs); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "can't do binary op between '%q' and '%q'", + vtype_to_qstr(vtype_lhs), vtype_to_qstr(vtype_rhs)); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } } @@ -2302,7 +2325,9 @@ STATIC void emit_native_return_value(emit_t *emit) { vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_RET); if (vtype != emit->return_vtype) { - mp_printf(&mp_plat_print, "ViperTypeError: incompatible return type\n"); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "return expected '%q' but got '%q'", + vtype_to_qstr(emit->return_vtype), vtype_to_qstr(vtype)); } } } else { @@ -2320,7 +2345,7 @@ STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { vtype_kind_t vtype_exc; emit_pre_pop_reg(emit, &vtype_exc, REG_ARG_1); // arg1 = object to raise if (vtype_exc != VTYPE_PYOBJ) { - mp_printf(&mp_plat_print, "ViperTypeError: must raise an object\n"); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "must raise an object"); } // 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); diff --git a/py/modbuiltins.c b/py/modbuiltins.c index bec47787c8..455e1cc1b6 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -703,6 +703,9 @@ STATIC const mp_map_elem_t mp_module_builtins_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_UnicodeError), (mp_obj_t)&mp_type_UnicodeError }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_ValueError), (mp_obj_t)&mp_type_ValueError }, + #if MICROPY_EMIT_NATIVE + { MP_OBJ_NEW_QSTR(MP_QSTR_ViperTypeError), (mp_obj_t)&mp_type_ViperTypeError }, + #endif { MP_OBJ_NEW_QSTR(MP_QSTR_ZeroDivisionError), (mp_obj_t)&mp_type_ZeroDivisionError }, // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/ // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation diff --git a/py/obj.h b/py/obj.h index 86f560ff51..11c0198bb9 100644 --- a/py/obj.h +++ b/py/obj.h @@ -434,6 +434,7 @@ extern const mp_obj_type_t mp_type_SystemExit; extern const mp_obj_type_t mp_type_TypeError; extern const mp_obj_type_t mp_type_UnicodeError; extern const mp_obj_type_t mp_type_ValueError; +extern const mp_obj_type_t mp_type_ViperTypeError; extern const mp_obj_type_t mp_type_ZeroDivisionError; // Constant objects, globally accessible diff --git a/py/objexcept.c b/py/objexcept.c index 4623e7318f..6c108d99cb 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -252,6 +252,10 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) */ //MP_DEFINE_EXCEPTION(SystemError, Exception) MP_DEFINE_EXCEPTION(TypeError, Exception) +#if MICROPY_EMIT_NATIVE + MP_DEFINE_EXCEPTION_BASE(TypeError) + MP_DEFINE_EXCEPTION(ViperTypeError, TypeError) +#endif MP_DEFINE_EXCEPTION(ValueError, Exception) #if MICROPY_PY_BUILTINS_STR_UNICODE MP_DEFINE_EXCEPTION_BASE(ValueError) diff --git a/py/qstrdefs.h b/py/qstrdefs.h index acf63e738f..d50fc1f5e2 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -144,6 +144,9 @@ Q(SystemExit) Q(TypeError) Q(UnboundLocalError) Q(ValueError) +#if MICROPY_EMIT_NATIVE +Q(ViperTypeError) +#endif Q(ZeroDivisionError) #if MICROPY_PY_BUILTINS_STR_UNICODE Q(UnicodeError)