From e9dac3b4d039997f446b6a615d580d284497d59b Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 29 Sep 2014 22:10:41 +0100 Subject: [PATCH] py: Add casting to viper; add native mem stores to viper. Viper can now do the following: def store(p:ptr8, c:int): p[0] = c This does a store of c to the memory pointed to by p using a machine instructions inline in the code. --- py/emitnative.c | 305 ++++++++++++++++------ py/nativeglue.c | 12 +- py/qstrdefs.h | 3 + tests/micropython/viper_ptr8_store.py | 29 ++ tests/micropython/viper_ptr8_store.py.exp | 4 + 5 files changed, 271 insertions(+), 82 deletions(-) create mode 100644 tests/micropython/viper_ptr8_store.py create mode 100644 tests/micropython/viper_ptr8_store.py.exp diff --git a/py/emitnative.c b/py/emitnative.c index d58da7e788..16f0a08246 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -148,6 +148,10 @@ #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_x64_add_r64_r64((as), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x64_sub_r64_r64((as), (reg_dest), (reg_src)) +#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x64_mov_r64_to_disp((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x64_mov_r8_to_disp((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x64_mov_r16_to_disp((as), (reg_src), (reg_base), 0) + #elif N_X86 // x86 specific stuff @@ -269,6 +273,10 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_x86_add_r32_r32((as), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x86_sub_r32_r32((as), (reg_dest), (reg_src)) +#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_disp((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x86_mov_r8_to_disp((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x86_mov_r16_to_disp((as), (reg_src), (reg_base), 0) + #elif N_THUMB // thumb specific stuff @@ -341,6 +349,10 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_thumb_add_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_thumb_sub_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src)) +#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_thumb_strb_rlo_rlo_i5((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_thumb_strh_rlo_rlo_i5((as), (reg_src), (reg_base), 0) + #elif N_ARM // ARM specific stuff @@ -414,6 +426,11 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_arm_add_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_arm_sub_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) +// TODO someone please implement str +#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_arm_str_reg_reg_i5((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_arm_strb_reg_reg_i5((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_arm_strh_reg_reg_i5((as), (reg_src), (reg_base), 0) + #else #error unknown native emitter @@ -426,15 +443,21 @@ typedef enum { STACK_IMM, } stack_info_kind_t; +// these enums must be distinct and the bottom 2 bits +// must correspond to the correct MP_NATIVE_TYPE_xxx value typedef enum { - VTYPE_PYOBJ = MP_NATIVE_TYPE_OBJ, - VTYPE_BOOL = MP_NATIVE_TYPE_BOOL, - VTYPE_INT = MP_NATIVE_TYPE_INT, - VTYPE_UINT = MP_NATIVE_TYPE_UINT, - VTYPE_UNBOUND, - VTYPE_PTR, - VTYPE_PTR_NONE, - VTYPE_BUILTIN_V_INT, + 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 = 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_PTR_NONE = 0x40 | MP_NATIVE_TYPE_UINT, + + VTYPE_UNBOUND = 0x50 | MP_NATIVE_TYPE_OBJ, + VTYPE_BUILTIN_CAST = 0x60 | MP_NATIVE_TYPE_OBJ, } vtype_kind_t; typedef struct _stack_info_t { @@ -495,6 +518,9 @@ STATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t ar case MP_QSTR_bool: type = VTYPE_BOOL; break; case MP_QSTR_int: type = VTYPE_INT; break; case MP_QSTR_uint: type = VTYPE_UINT; break; + 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: printf("ViperTypeError: unknown type %s\n", qstr_str(arg2)); return; } if (op == MP_EMIT_NATIVE_TYPE_RETURN) { @@ -606,6 +632,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop } } + // TODO don't load r7 if we don't need it asm_thumb_mov_reg_i32(emit->as, ASM_THUMB_REG_R7, (mp_uint_t)mp_fun_table); #elif N_ARM for (int i = 0; i < scope->num_pos_args; i++) { @@ -623,6 +650,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop } } + // TODO don't load r7 if we don't need it asm_arm_mov_reg_i32(emit->as, ASM_ARM_REG_R7, (mp_uint_t)mp_fun_table); #else #error not implemented @@ -645,7 +673,7 @@ STATIC void emit_native_end_pass(emit_t *emit) { mp_uint_t f_len = ASM_GET_CODE_SIZE(emit->as); // compute type signature - // TODO check that viper types here convert correctly to valid types for emit glue + // 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; for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) { type_sig |= (emit->local_vtype[i] & 3) << (i * 2 + 2); @@ -796,12 +824,26 @@ STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int re } } -// If stacked value is in a register, then *reg_dest is set to that register. -// Otherwise, the value is put in *reg_dest. -STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest) { +// does an efficient X=pop(); discard(); push(X) +// needs a (non-temp) register in case the poped element was stored in the stack +STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) { + stack_info_t *si = &emit->stack_info[emit->stack_size - 2]; + si[0] = si[1]; + if (si->kind == STACK_VALUE) { + // if folded element was on the stack we need to put it in a register + ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - 1, reg_dest); + si->kind = STACK_REG; + si->u_reg = reg_dest; + } + adjust_stack(emit, -1); +} + +// If stacked value is in a register and the register is not r1 or r2, then +// *reg_dest is set to that register. Otherwise the value is put in *reg_dest. +STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest, int not_r1, int not_r2) { emit->last_emit_was_return_value = false; stack_info_t *si = peek_stack(emit, 0); - if (si->kind == STACK_REG) { + if (si->kind == STACK_REG && si->u_reg != not_r1 && si->u_reg != not_r2) { *vtype = si->vtype; *reg_dest = si->u_reg; need_reg_single(emit, *reg_dest, 1); @@ -836,6 +878,11 @@ STATIC void emit_pre_pop_reg_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int reg STATIC void emit_post(emit_t *emit) { } +STATIC void emit_post_top_set_vtype(emit_t *emit, vtype_kind_t new_vtype) { + stack_info_t *si = &emit->stack_info[emit->stack_size - 1]; + si->vtype = new_vtype; +} + STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) { stack_info_t *si = &emit->stack_info[emit->stack_size]; si->vtype = vtype; @@ -954,6 +1001,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, si->vtype, REG_ARG_2); // arg2 = type ASM_MOV_REG_TO_LOCAL(emit->as, REG_RET, local_num); si->vtype = VTYPE_PYOBJ; + DEBUG_printf(" convert_native_to_obj(local_num=" UINT_FMT ")\n", local_num); } } @@ -1173,9 +1221,23 @@ STATIC void emit_native_load_name(emit_t *emit, qstr qst) { } STATIC void emit_native_load_global(emit_t *emit, qstr qst) { + DEBUG_printf("load_global(%s)\n", qstr_str(qst)); emit_native_pre(emit); - emit_call_with_imm_arg(emit, MP_F_LOAD_GLOBAL, qst, REG_ARG_1); - emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); + // check for builtin casting operators + if (emit->do_viper_types && qst == MP_QSTR_int) { + emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_INT); + } else if (emit->do_viper_types && qst == MP_QSTR_uint) { + emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_UINT); + } else if (emit->do_viper_types && qst == MP_QSTR_ptr) { + emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR); + } else if (emit->do_viper_types && qst == MP_QSTR_ptr8) { + emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR8); + } else if (emit->do_viper_types && qst == MP_QSTR_ptr16) { + emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR16); + } else { + emit_call_with_imm_arg(emit, MP_F_LOAD_GLOBAL, qst, REG_ARG_1); + emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); + } } STATIC void emit_native_load_attr(emit_t *emit, qstr qst) { @@ -1314,16 +1376,103 @@ STATIC void emit_native_store_attr(emit_t *emit, qstr qst) { } STATIC void emit_native_store_subscr(emit_t *emit) { - // depends on type of subject: - // - integer, function, pointer to structure: error - // - pointer to integers: store as per array - // - Python object: call runtime with converted object or type info - vtype_kind_t vtype_index, vtype_base, vtype_value; - emit_pre_pop_reg_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1, &vtype_value, REG_ARG_3); // index, base, value to store - assert(vtype_index == VTYPE_PYOBJ); - assert(vtype_base == VTYPE_PYOBJ); - assert(vtype_value == VTYPE_PYOBJ); - emit_call(emit, MP_F_OBJ_SUBSCR); + DEBUG_printf("store_subscr\n"); + // need to compile: base[index] = value + + // pop: index, base, value + // optimise case where index is an immediate + vtype_kind_t vtype_base = peek_vtype(emit, 1); + + if (vtype_base == VTYPE_PYOBJ) { + // standard Python call + vtype_kind_t vtype_index, vtype_value; + emit_pre_pop_reg_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1, &vtype_value, REG_ARG_3); + assert(vtype_index == VTYPE_PYOBJ); + assert(vtype_value == VTYPE_PYOBJ); + emit_call(emit, MP_F_OBJ_SUBSCR); + } else { + // viper call + stack_info_t *top = peek_stack(emit, 0); + if (top->vtype == VTYPE_INT && top->kind == STACK_IMM) { + // index is an immediate + mp_int_t index_value = top->u_imm; + emit_pre_pop_discard(emit); // discard index + vtype_kind_t vtype_value; + int reg_base = REG_ARG_1; + int reg_index = REG_ARG_2; + int reg_value = REG_ARG_3; + emit_pre_pop_reg_flexible(emit, &vtype_base, ®_base, reg_index, reg_value); + emit_pre_pop_reg_flexible(emit, &vtype_value, ®_value, reg_base, reg_index); + switch (vtype_base) { + case VTYPE_PTR8: { + // pointer to 8-bit memory + // TODO optimise to use thumb strb r1, [r2, r3] + if (index_value != 0) { + // index is non-zero + #if N_THUMB + if (index_value > 0 && index_value < 32) { + asm_thumb_strb_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); + break; + } + #endif + ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index); + ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base + reg_base = reg_index; + } + ASM_STORE8_REG_REG(emit->as, reg_value, reg_base); // store value to (base+index) + break; + } + case VTYPE_PTR16: { + // pointer to 16-bit memory + if (index_value != 0) { + // index is a non-zero immediate + #if N_THUMB + if (index_value > 0 && index_value < 32) { + asm_thumb_strh_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); + break; + } + #endif + ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index); + ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base + reg_base = reg_index; + } + ASM_STORE16_REG_REG(emit->as, reg_value, reg_base); // store value to (base+2*index) + break; + } + default: + printf("ViperTypeError: can't store to type %d\n", vtype_base); + } + } else { + // index is not an immediate + vtype_kind_t vtype_index, vtype_value; + int reg_index = REG_ARG_2; + int reg_value = REG_ARG_3; + emit_pre_pop_reg_flexible(emit, &vtype_index, ®_index, REG_ARG_1, reg_value); + emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); + emit_pre_pop_reg_flexible(emit, &vtype_value, ®_value, REG_ARG_1, reg_index); + switch (vtype_base) { + case VTYPE_PTR8: { + // pointer to 8-bit memory + // TODO optimise to use thumb strb r1, [r2, r3] + assert(vtype_index == VTYPE_INT); + ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base + ASM_STORE8_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+index) + break; + } + case VTYPE_PTR16: { + // pointer to 16-bit memory + assert(vtype_index == VTYPE_INT); + ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base + ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base + ASM_STORE16_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+2*index) + break; + } + default: + printf("ViperTypeError: can't store to type %d\n", vtype_base); + } + } + + } } STATIC void emit_native_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { @@ -1581,7 +1730,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { } #endif int reg_rhs = REG_ARG_3; - emit_pre_pop_reg_flexible(emit, &vtype_rhs, ®_rhs); + emit_pre_pop_reg_flexible(emit, &vtype_rhs, ®_rhs, REG_RET, REG_ARG_2); emit_pre_pop_reg(emit, &vtype_lhs, REG_ARG_2); if (0) { // dummy @@ -1813,64 +1962,53 @@ STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_c STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { DEBUG_printf("call_function(n_pos=" UINT_FMT ", n_kw=" UINT_FMT ", star_flags=" UINT_FMT ")\n", n_positional, n_keyword, star_flags); - // call special viper runtime routine with type info for args, and wanted type info for return + // TODO: in viper mode, call special runtime routine with type info for args, + // and wanted type info for return, to remove need for boxing/unboxing + assert(!star_flags); - /* we no longer have these _n specific call_function's - * they anyway push args into an array - * and they would take too much room in the native dispatch table - if (n_positional == 0) { - vtype_kind_t vtype_fun; + emit_native_pre(emit); + vtype_kind_t vtype_fun = peek_vtype(emit, n_positional + 2 * n_keyword); + if (vtype_fun == VTYPE_BUILTIN_CAST) { + // casting operator + assert(n_positional == 1 && n_keyword == 0); + DEBUG_printf(" cast to %d\n", vtype_fun); + vtype_kind_t vtype_cast = peek_stack(emit, 1)->u_imm; + switch (peek_vtype(emit, 0)) { + case VTYPE_PYOBJ: { + 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_post_push_reg(emit, vtype_cast, REG_RET); + break; + } + case VTYPE_BOOL: + case VTYPE_INT: + case VTYPE_UINT: + case VTYPE_PTR: + case VTYPE_PTR8: + case VTYPE_PTR16: + case VTYPE_PTR_NONE: + emit_fold_stack_top(emit, REG_ARG_1); + emit_post_top_set_vtype(emit, vtype_cast); + break; + default: + assert(!"TODO: convert obj to int"); + } + } else { + if (n_positional != 0 || n_keyword != 0) { + emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args + } emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function assert(vtype_fun == VTYPE_PYOBJ); - emit_call(emit, MP_F_CALL_FUNCTION_0); - } else if (n_positional == 1) { - vtype_kind_t vtype_fun, vtype_arg1; - emit_pre_pop_reg_reg(emit, &vtype_arg1, REG_ARG_2, &vtype_fun, REG_ARG_1); // the single argument, the function - assert(vtype_fun == VTYPE_PYOBJ); - assert(vtype_arg1 == VTYPE_PYOBJ); - emit_call(emit, MP_F_CALL_FUNCTION_1); - } else if (n_positional == 2) { - vtype_kind_t vtype_fun, vtype_arg1, vtype_arg2; - emit_pre_pop_reg_reg_reg(emit, &vtype_arg2, REG_ARG_3, &vtype_arg1, REG_ARG_2, &vtype_fun, REG_ARG_1); // the second argument, the first argument, the function - assert(vtype_fun == VTYPE_PYOBJ); - assert(vtype_arg1 == VTYPE_PYOBJ); - assert(vtype_arg2 == VTYPE_PYOBJ); - emit_call(emit, MP_F_CALL_FUNCTION_2); - } else { - */ - - emit_native_pre(emit); - if (n_positional != 0 || n_keyword != 0) { - emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args + emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2); + emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } - vtype_kind_t vtype_fun; - emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function - assert(vtype_fun == VTYPE_PYOBJ); - emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2); - emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { assert(!star_flags); - - /* - if (n_positional == 0) { - vtype_kind_t vtype_meth, vtype_self; - emit_pre_pop_reg_reg(emit, &vtype_self, REG_ARG_2, &vtype_meth, REG_ARG_1); // the self object (or NULL), the method - assert(vtype_meth == VTYPE_PYOBJ); - assert(vtype_self == VTYPE_PYOBJ); - emit_call(emit, MP_F_CALL_METHOD_1); - } else if (n_positional == 1) { - vtype_kind_t vtype_meth, vtype_self, vtype_arg1; - emit_pre_pop_reg_reg_reg(emit, &vtype_arg1, REG_ARG_3, &vtype_self, REG_ARG_2, &vtype_meth, REG_ARG_1); // the first argument, the self object (or NULL), the method - assert(vtype_meth == VTYPE_PYOBJ); - assert(vtype_self == VTYPE_PYOBJ); - assert(vtype_arg1 == VTYPE_PYOBJ); - emit_call(emit, MP_F_CALL_METHOD_2); - } else { - */ - emit_native_pre(emit); emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 2 + n_positional + 2 * n_keyword); // pointer to items, including meth and self emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, n_positional, REG_ARG_1, n_keyword, REG_ARG_2); @@ -1879,17 +2017,24 @@ STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uin STATIC void emit_native_return_value(emit_t *emit) { DEBUG_printf("return_value\n"); - vtype_kind_t vtype; - emit_pre_pop_reg(emit, &vtype, REG_RET); if (emit->do_viper_types) { - if (vtype == VTYPE_PTR_NONE) { + if (peek_vtype(emit, 0) == VTYPE_PTR_NONE) { + emit_pre_pop_discard(emit); if (emit->return_vtype == VTYPE_PYOBJ) { ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_RET); + } else { + ASM_MOV_IMM_TO_REG(emit->as, 0, REG_RET); + } + } else { + vtype_kind_t vtype; + emit_pre_pop_reg(emit, &vtype, REG_RET); + if (vtype != emit->return_vtype) { + printf("ViperTypeError: incompatible return type\n"); } - } else if (vtype != emit->return_vtype) { - printf("ViperTypeError: incompatible return type\n"); } } else { + vtype_kind_t vtype; + emit_pre_pop_reg(emit, &vtype, REG_RET); assert(vtype == VTYPE_PYOBJ); } emit->last_emit_was_return_value = true; diff --git a/py/nativeglue.c b/py/nativeglue.c index 235c4a4dbe..05fadb7b0d 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -51,8 +51,16 @@ mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) { switch (type & 3) { case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj; case MP_NATIVE_TYPE_BOOL: - case MP_NATIVE_TYPE_INT: - case MP_NATIVE_TYPE_UINT: return mp_obj_get_int(obj); + case MP_NATIVE_TYPE_INT: return mp_obj_get_int(obj); + case MP_NATIVE_TYPE_UINT: { + mp_buffer_info_t bufinfo; + if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_RW)) { + return (mp_uint_t)bufinfo.buf; + } else { + // TODO should be mp_obj_get_uint_truncated or something + return mp_obj_get_int(obj); + } + } default: assert(0); return 0; } } diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 070e673f73..fda140f11f 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -77,6 +77,9 @@ Q(const) Q(native) Q(viper) Q(uint) +Q(ptr) +Q(ptr8) +Q(ptr16) #endif #if MICROPY_EMIT_INLINE_THUMB diff --git a/tests/micropython/viper_ptr8_store.py b/tests/micropython/viper_ptr8_store.py new file mode 100644 index 0000000000..fc24290c99 --- /dev/null +++ b/tests/micropython/viper_ptr8_store.py @@ -0,0 +1,29 @@ +# test ptr8 type + +@micropython.viper +def set(dest:ptr8, val:int): + dest[0] = val + +@micropython.viper +def memset(dest:ptr8, val:int, n:int): + for i in range(n): + dest[i] = val + +@micropython.viper +def memset2(dest_in, val:int): + dest = ptr8(dest_in) + n = int(len(dest_in)) + for i in range(n): + dest[i] = val + +b = bytearray(4) +print(b) + +set(b, 42) +print(b) + +memset(b, 43, len(b)) +print(b) + +memset2(b, 44) +print(b) diff --git a/tests/micropython/viper_ptr8_store.py.exp b/tests/micropython/viper_ptr8_store.py.exp new file mode 100644 index 0000000000..30ca5b10ea --- /dev/null +++ b/tests/micropython/viper_ptr8_store.py.exp @@ -0,0 +1,4 @@ +bytearray(b'\x00\x00\x00\x00') +bytearray(b'*\x00\x00\x00') +bytearray(b'++++') +bytearray(b',,,,')