8000 py/inlineasm: Add ability to specify return type of asm_thumb funcs. · lispmeister/micropython@8f54c08 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8f54c08

Browse files
committed
py/inlineasm: Add ability to specify return type of asm_thumb funcs.
Supported return types are: object, bool, int, uint. For example: @micropython.asm_thumb def foo(r0, r1) -> uint: add(r0, r0, r1)
1 parent 3d42aa0 commit 8f54c08

File tree

10 files changed

+65
-16
lines changed

10 files changed

+65
-16
lines changed

py/compile.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2936,7 +2936,24 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
29362936
}
29372937
}
29382938

2939-
assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
2939+
// pns->nodes[2] is function return annotation
2940+
mp_uint_t type_sig = MP_NATIVE_TYPE_INT;
2941+
mp_parse_node_t pn_annotation = pns->nodes[2];
2942+
if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
2943+
// nodes[2] can be null or a test-expr
2944+
if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
2945+
qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
2946+
switch (ret_type) {
2947+
case MP_QSTR_object: type_sig = MP_NATIVE_TYPE_OBJ; break;
2948+
case MP_QSTR_bool: type_sig = MP_NATIVE_TYPE_BOOL; break;
2949+
case MP_QSTR_int: type_sig = MP_NATIVE_TYPE_INT; break;
2950+
case MP_QSTR_uint: type_sig = MP_NATIVE_TYPE_UINT; break;
2951+
default: compile_syntax_error(comp, pn_annotation, "unknown type"); return;
2952+
}
2953+
} else {
2954+
compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier");
2955+
}
2956+
}
29402957

29412958
mp_parse_node_t pn_body = pns->nodes[3]; // body
29422959
mp_parse_node_t *nodes;
@@ -3028,7 +3045,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
30283045
}
30293046

30303047
if (comp->pass > MP_PASS_SCOPE) {
3031-
EMIT_INLINE_ASM(end_pass);
3048+
EMIT_INLINE_ASM_ARG(end_pass, type_sig);
30323049
}
30333050

30343051
if (comp->compile_error != MP_OBJ_NULL) {

py/emit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ typedef struct _emit_inline_asm_t emit_inline_asm_t;
268268

269269
typedef struct _emit_inline_asm_method_table_t {
270270
void (*start_pass)(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope, mp_obj_t *error_slot);
271-
void (*end_pass)(emit_inline_asm_t *emit);
271+
void (*end_pass)(emit_inline_asm_t *emit, mp_uint_t type_sig);
272272
mp_uint_t (*count_params)(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params);
273273
bool (*label)(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id);
274274
void (*align)(emit_inline_asm_t *emit, mp_uint_t align);

py/emitglue.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp
162162
#endif
163163
#if MICROPY_EMIT_INLINE_THUMB
164164
case MP_CODE_NATIVE_ASM:
165-
fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->data.u_native.fun_data);
165+
fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
166166
break;
167167
#endif
168168
default:

py/emitinlinethumb.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,14 @@ STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pa
8484
asm_thumb_entry(emit->as, 0);
8585
}
8686

87-
STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
87+
STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {
8888
asm_thumb_exit(emit->as);
8989
asm_thumb_end_pass(emit->as);
9090

9191
if (emit->pass == MP_PASS_EMIT) {
9292
void *f = asm_thumb_get_code(emit->as);
93-
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f, asm_thumb_get_code_size(emit->as), NULL, emit->scope->num_pos_args, 0, 0);
93+
mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f,
94+
asm_thumb_get_code_size(emit->as), NULL, emit->scope->num_pos_args, 0, type_sig);
9495
}
9596
}
9697

py/nativeglue.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@
3434
#include "py/emitglue.h"
3535
#include "py/bc.h"
3636

37-
#if MICROPY_EMIT_NATIVE
38-
3937
#if 0 // print debugging info
40 F438 38
#define DEBUG_printf DEBUG_printf
4139
#else // don't print debugging info
4240
#define DEBUG_printf(...) (void)0
4341
#endif
4442

43+
#if MICROPY_EMIT_NATIVE
44+
4545
// convert a Micro Python object to a valid native value based on type
4646
mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) {
4747
DEBUG_printf("mp_convert_obj_to_native(%p, " UINT_FMT ")\n", obj, type);
@@ -61,6 +61,10 @@ mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) {
6161
}
6262
}
6363

64+
#endif
65+
66+
#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
67+
6468
// convert a native value to a Micro Python object based on type
6569
mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type) {
6670
DEBUG_printf("mp_convert_native_to_obj(" UINT_FMT ", " UINT_FMT ")\n", val, type);
@@ -73,6 +77,10 @@ mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type) {
7377
}
7478
}
7579

80+
#endif
81+
82+
#if MICROPY_EMIT_NATIVE
83+
7684
// wrapper that accepts n_args and n_kw in one argument
7785
// (native emitter can only pass at most 3 arguments to a function)
7886
mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, const mp_obj_t *args) {

py/obj.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
625625
mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table);
626626
mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data, const mp_uint_t *const_table);
627627
mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig);
628-
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data);
628+
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig);
629629
mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun);
630630
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_uint_t n_closed, const mp_obj_t *closed);
631631
mp_obj_t mp_obj_new_tuple(mp_uint_t n, const mp_obj_t *items);

py/objfun.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ typedef struct _mp_obj_fun_asm_t {
452452
mp_obj_base_t base;
453453
mp_uint_t n_args;
454454
void *fun_data; // GC must be able to trace this pointer
455+
mp_uint_t type_sig;
455456
} mp_obj_fun_asm_t;
456457

457458
typedef mp_uint_t (*inline_asm_fun_0_t)(void);
@@ -509,11 +510,6 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
509510
}
510511
}
511512

512-
// convert a return value from inline asm to a sensible Micro Python object
513-
STATIC mp_obj_t convert_val_from_inline_asm(mp_uint_t val) {
514-
return MP_OBJ_NEW_SMALL_INT(val);
515-
}
516-
517513
STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
518514
mp_obj_fun_asm_t *self = self_in;
519515

@@ -535,7 +531,7 @@ STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
535531
ret = 0;
536532
}
537533

538-
return convert_val_from_inline_asm(ret);
534+
return mp_convert_native_to_obj(ret, self->type_sig);
539535
}
540536

541537
STATIC const mp_obj_type_t mp_type_fun_asm = {
@@ -545,11 +541,12 @@ STATIC const mp_obj_type_t mp_type_fun_asm = {
545541
.unary_op = mp_generic_unary_op,
546542
};
547543

548-
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data) {
544+
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig) {
549545
mp_obj_fun_asm_t *o = m_new_obj(mp_obj_fun_asm_t);
550546
o->base.type = &mp_type_fun_asm;
551547
o->n_args = n_args;
552548
o->fun_data = fun_data;
549+
o->type_sig = type_sig;
553550
return o;
554551
}
555552

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ Q(asm_thumb)
113113
Q(label)
114114
Q(align)
115115
Q(data)
116+
Q(uint)
116117
#endif
117118

118119
Q(builtins)

tests/inlineasm/asmrettype.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# test return type of inline asm
2+
3+
@micropython.asm_thumb
4+
def ret_obj(r0) -> object:
5+
pass
6+
ret_obj(print)(1)
7+
8+
@micropython.asm_thumb
9+
def ret_bool(r0) -> bool:
10+
pass
11+
print(ret_bool(0), ret_bool(1))
12+
13+
@micropython.asm_thumb
14+
def ret_int(r0) -> int:
15+
lsl(r0, r0, 29)
16+
print(ret_int(0), hex(ret_int(1)), hex(ret_int(2)), hex(ret_int(4)))
17+
18+
@micropython.asm_thumb
19+
def ret_uint(r0) -> uint:
20+
lsl(r0, r0, 29)
21+
print(ret_uint(0), hex(ret_uint(1)), hex(ret_uint(2)), hex(ret_uint(4)))

tests/inlineasm/asmrettype.py.exp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
1
2+
False True
3+
0 0x20000000 0x40000000 -0x80000000
4+
0 0x20000000 0x40000000 0x80000000

0 commit comments

Comments
 (0)
0