From 5f3e005b6791634b104fa6385c8a9bf5ed1af164 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 2 Feb 2016 23:16:05 +0000 Subject: [PATCH] py: Extend native type-sig to use 4 bits, so uint is separate to ptr. Before this patch, the native types for uint and ptr/ptr8/ptr16/ptr32 all overlapped and it was possible to make a mistake in casting. Now, these types are all separate and any coding mistakes will be raised as runtime errors. --- py/emitnative.c | 20 ++++++++++---------- py/nativeglue.c | 21 ++++++++++----------- py/objfun.c | 14 +++++++------- py/runtime0.h | 4 ++++ 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/py/emitnative.c b/py/emitnative.c index 65908070f..4d9463230 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -510,19 +510,19 @@ typedef enum { STACK_IMM, } stack_info_kind_t; -// these enums must be distinct and the bottom 2 bits +// these enums must be distinct and the bottom 4 bits // must correspond to the correct MP_NATIVE_TYPE_xxx value typedef enum { VTYPE_PYOBJ = 0x00 | MP_NATIVE_TYPE_OBJ, VTYPE_BOOL = 0x00 | MP_NATIVE_TYPE_BOOL, VTYPE_INT = 0x00 | MP_NATIVE_TYPE_INT, VTYPE_UINT = 0x00 | MP_NATIVE_TYPE_UINT, + VTYPE_PTR = 0x00 | MP_NATIVE_TYPE_PTR, + VTYPE_PTR8 = 0x00 | MP_NATIVE_TYPE_PTR8, + VTYPE_PTR16 = 0x00 | MP_NATIVE_TYPE_PTR16, + VTYPE_PTR32 = 0x00 | MP_NATIVE_TYPE_PTR32, - VTYPE_PTR = 0x10 | MP_NATIVE_TYPE_UINT, // pointer to word sized entity - VTYPE_PTR8 = 0x20 | MP_NATIVE_TYPE_UINT, - VTYPE_PTR16 = 0x30 | MP_NATIVE_TYPE_UINT, - VTYPE_PTR32 = 0x40 | MP_NATIVE_TYPE_UINT, - VTYPE_PTR_NONE = 0x50 | MP_NATIVE_TYPE_UINT, + VTYPE_PTR_NONE = 0x50 | MP_NATIVE_TYPE_PTR, VTYPE_UNBOUND = 0x60 | MP_NATIVE_TYPE_OBJ, VTYPE_BUILTIN_CAST = 0x70 | MP_NATIVE_TYPE_OBJ, @@ -882,10 +882,10 @@ STATIC void emit_native_end_pass(emit_t *emit) { mp_uint_t f_len = ASM_GET_CODE_SIZE(emit->as); // compute type signature - // note that the lower 2 bits of a vtype are tho correct MP_NATIVE_TYPE_xxx - mp_uint_t type_sig = emit->return_vtype & 3; + // note that the lower 4 bits of a vtype are tho correct MP_NATIVE_TYPE_xxx + mp_uint_t type_sig = emit->return_vtype & 0xf; for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) { - type_sig |= (emit->local_vtype[i] & 3) << (i * 2 + 2); + type_sig |= (emit->local_vtype[i] & 0xf) << (i * 4 + 4); } mp_emit_glue_assign_native(emit->scope->raw_code, @@ -2382,7 +2382,7 @@ STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_u vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_1); emit_pre_pop_discard(emit); - emit_call_with_imm_arg(emit, MP_F_CONVERT_OBJ_TO_NATIVE, MP_NATIVE_TYPE_UINT, REG_ARG_2); // arg2 = type + emit_call_with_imm_arg(emit, MP_F_CONVERT_OBJ_TO_NATIVE, vtype_cast, REG_ARG_2); // arg2 = type emit_post_push_reg(emit, vtype_cast, REG_RET); break; } diff --git a/py/nativeglue.c b/py/nativeglue.c index cc0d61ce9..e27d69e14 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -45,19 +45,16 @@ // convert a Micro Python object to a valid native value based on type mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) { DEBUG_printf("mp_convert_obj_to_native(%p, " UINT_FMT ")\n", obj, type); - switch (type & 3) { + switch (type & 0xf) { case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj; case MP_NATIVE_TYPE_BOOL: - case MP_NATIVE_TYPE_INT: return mp_obj_get_int_truncated(obj); - case MP_NATIVE_TYPE_UINT: { + case MP_NATIVE_TYPE_INT: + case MP_NATIVE_TYPE_UINT: return mp_obj_get_int_truncated(obj); + default: { // a pointer mp_buffer_info_t bufinfo; - if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_RW)) { - return (mp_uint_t)bufinfo.buf; - } else { - return mp_obj_get_int_truncated(obj); - } + mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_RW); + return (mp_uint_t)bufinfo.buf; } - default: assert(0); return 0; } } @@ -68,12 +65,14 @@ mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) { // convert a native value to a Micro Python object based on type mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type) { DEBUG_printf("mp_convert_native_to_obj(" UINT_FMT ", " UINT_FMT ")\n", val, type); - switch (type & 3) { + switch (type & 0xf) { case MP_NATIVE_TYPE_OBJ: return (mp_obj_t)val; case MP_NATIVE_TYPE_BOOL: return mp_obj_new_bool(val); case MP_NATIVE_TYPE_INT: return mp_obj_new_int(val); case MP_NATIVE_TYPE_UINT: return mp_obj_new_int_from_uint(val); - default: assert(0); return mp_const_none; + default: // a pointer + // we return just the value of the pointer as an integer + return mp_obj_new_int_from_uint(val); } } diff --git a/py/objfun.c b/py/objfun.c index df7d16213..3deb0c01d 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -404,17 +404,17 @@ STATIC mp_obj_t fun_viper_call(mp_obj_t self_in, size_t n_args, size_t n_kw, con if (n_args == 0) { ret = ((viper_fun_0_t)fun)(); } else if (n_args == 1) { - ret = ((viper_fun_1_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 2)); + ret = ((viper_fun_1_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 4)); } else if (n_args == 2) { - ret = ((viper_fun_2_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 2), mp_convert_obj_to_native(args[1], self->type_sig >> 4)); + ret = ((viper_fun_2_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 4), mp_convert_obj_to_native(args[1], self->type_sig >> 8)); } else if (n_args == 3) { - ret = ((viper_fun_3_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 2), mp_convert_obj_to_native(args[1], self->type_sig >> 4), mp_convert_obj_to_native(args[2], self->type_sig >> 6)); + ret = ((viper_fun_3_t)fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 4), mp_convert_obj_to_native(args[1], self->type_sig >> 8), mp_convert_obj_to_native(args[2], self->type_sig >> 12)); } else if (n_args == 4) { ret = ((viper_fun_4_t)fun)( - mp_convert_obj_to_native(args[0], self->type_sig >> 2), - mp_convert_obj_to_native(args[1], self->type_sig >> 4), - mp_convert_obj_to_native(args[2], self->type_sig >> 6), - mp_convert_obj_to_native(args[3], self->type_sig >> 8) + mp_convert_obj_to_native(args[0], self->type_sig >> 4), + mp_convert_obj_to_native(args[1], self->type_sig >> 8), + mp_convert_obj_to_native(args[2], self->type_sig >> 12), + mp_convert_obj_to_native(args[3], self->type_sig >> 16) ); } else { // TODO 5 or more arguments not supported for viper call diff --git a/py/runtime0.h b/py/runtime0.h index 6417cfd03..8d62403a7 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -37,6 +37,10 @@ #define MP_NATIVE_TYPE_BOOL (0x01) #define MP_NATIVE_TYPE_INT (0x02) #define MP_NATIVE_TYPE_UINT (0x03) +#define MP_NATIVE_TYPE_PTR (0x04) +#define MP_NATIVE_TYPE_PTR8 (0x05) +#define MP_NATIVE_TYPE_PTR16 (0x06) +#define MP_NATIVE_TYPE_PTR32 (0x07) typedef enum { MP_UNARY_OP_BOOL, // __bool__