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.
This commit is contained in:
Damien George 2016-02-02 23:16:05 +00:00
parent 086d98cbde
commit 5f3e005b67
4 changed files with 31 additions and 28 deletions

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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__