summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/asmthumb.c4
-rw-r--r--py/asmthumb.h1
-rw-r--r--py/asmx64.c19
-rw-r--r--py/asmx64.h4
-rw-r--r--py/asmx86.c27
-rw-r--r--py/asmx86.h6
-rw-r--r--py/bc.c13
-rw-r--r--py/emitglue.c11
-rw-r--r--py/emitglue.h2
-rw-r--r--py/emitinlinethumb.c2
-rw-r--r--py/emitnative.c358
-rw-r--r--py/nativeglue.c2
-rw-r--r--py/obj.h2
-rw-r--r--py/objfun.c62
-rw-r--r--py/objgenerator.c3
-rw-r--r--py/runtime0.h1
-rwxr-xr-xtests/run-tests25
17 files changed, 307 insertions, 235 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 5bf2d80bb4..16337f4d5e 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -106,6 +106,10 @@ STATIC byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int num_bytes_to_
}
}
+uint asm_thumb_get_code_pos(asm_thumb_t *as) {
+ return as->code_offset;
+}
+
uint asm_thumb_get_code_size(asm_thumb_t *as) {
return as->code_size;
}
diff --git a/py/asmthumb.h b/py/asmthumb.h
index 1ce91d38d6..e40f956543 100644
--- a/py/asmthumb.h
+++ b/py/asmthumb.h
@@ -70,6 +70,7 @@ asm_thumb_t *asm_thumb_new(uint max_num_labels);
void asm_thumb_free(asm_thumb_t *as, bool free_code);
void asm_thumb_start_pass(asm_thumb_t *as, uint pass);
void asm_thumb_end_pass(asm_thumb_t *as);
+uint asm_thumb_get_code_pos(asm_thumb_t *as);
uint asm_thumb_get_code_size(asm_thumb_t *as);
void *asm_thumb_get_code(asm_thumb_t *as);
diff --git a/py/asmx64.c b/py/asmx64.c
index d501d2cc8c..05aa0c2f14 100644
--- a/py/asmx64.c
+++ b/py/asmx64.c
@@ -176,6 +176,10 @@ STATIC byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int num_bytes_to_writ
}
}
+mp_uint_t asm_x64_get_code_pos(asm_x64_t *as) {
+ return as->code_offset;
+}
+
mp_uint_t asm_x64_get_code_size(asm_x64_t *as) {
return as->code_size;
}
@@ -222,6 +226,21 @@ STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) {
c[7] = IMM64_L7(w64);
}
+// align must be a multiple of 2
+void asm_x64_align(asm_x64_t* as, mp_uint_t align) {
+ // TODO fill unused data with NOPs?
+ as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
+}
+
+void asm_x64_data(asm_x64_t* as, mp_uint_t bytesize, mp_uint_t val) {
+ byte *c = asm_x64_get_cur_to_write_bytes(as, bytesize);
+ // machine is little endian
+ for (uint i = 0; i < bytesize; i++) {
+ *c++ = val;
+ val >>= 8;
+ }
+}
+
/* unused
STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {
byte* c;
diff --git a/py/asmx64.h b/py/asmx64.h
index cb021b2f3c..0d3af9aa18 100644
--- a/py/asmx64.h
+++ b/py/asmx64.h
@@ -78,9 +78,13 @@ asm_x64_t* asm_x64_new(mp_uint_t max_num_labels);
void asm_x64_free(asm_x64_t* as, bool free_code);
void asm_x64_start_pass(asm_x64_t *as, uint pass);
void asm_x64_end_pass(asm_x64_t *as);
+mp_uint_t asm_x64_get_code_pos(asm_x64_t *as);
mp_uint_t asm_x64_get_code_size(asm_x64_t* as);
void* asm_x64_get_code(asm_x64_t* as);
+void asm_x64_align(asm_x64_t *as, mp_uint_t align);
+void asm_x64_data(asm_x64_t *as, mp_uint_t bytesize, mp_uint_t val);
+
void asm_x64_nop(asm_x64_t* as);
void asm_x64_push_r64(asm_x64_t* as, int src_r64);
void asm_x64_pop_r64(asm_x64_t* as, int dest_r64);
diff --git a/py/asmx86.c b/py/asmx86.c
index 3de2f12aa4..8a4383c82d 100644
--- a/py/asmx86.c
+++ b/py/asmx86.c
@@ -162,6 +162,10 @@ STATIC byte *asm_x86_get_cur_to_write_bytes(asm_x86_t *as, int num_bytes_to_writ
}
}
+mp_uint_t asm_x86_get_code_pos(asm_x86_t *as) {
+ return as->code_offset;
+}
+
mp_uint_t asm_x86_get_code_size(asm_x86_t *as) {
return as->code_size;
}
@@ -196,6 +200,21 @@ STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) {
c[3] = IMM32_L3(w32);
}
+// align must be a multiple of 2
+void asm_x86_align(asm_x86_t* as, mp_uint_t align) {
+ // TODO fill unused data with NOPs?
+ as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
+}
+
+void asm_x86_data(asm_x86_t* as, mp_uint_t bytesize, mp_uint_t val) {
+ byte *c = asm_x86_get_cur_to_write_bytes(as, bytesize);
+ // machine is little endian
+ for (uint i = 0; i < bytesize; i++) {
+ *c++ = val;
+ val >>= 8;
+ }
+}
+
STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) {
assert(disp_r32 != ASM_X86_REG_ESP);
@@ -541,7 +560,13 @@ void asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32)
void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32) {
// TODO align stack on 16-byte boundary before the call
- assert(n_args <= 3);
+ assert(n_args <= 5);
+ if (n_args > 4) {
+ asm_x86_push_r32(as, ASM_X86_REG_ARG_5);
+ }
+ if (n_args > 3) {
+ asm_x86_push_r32(as, ASM_X86_REG_ARG_4);
+ }
if (n_args > 2) {
asm_x86_push_r32(as, ASM_X86_REG_ARG_3);
}
diff --git a/py/asmx86.h b/py/asmx86.h
index 544786cf7f..cb245f37d9 100644
--- a/py/asmx86.h
+++ b/py/asmx86.h
@@ -61,6 +61,8 @@
#define ASM_X86_REG_ARG_1 ASM_X86_REG_EAX
#define ASM_X86_REG_ARG_2 ASM_X86_REG_ECX
#define ASM_X86_REG_ARG_3 ASM_X86_REG_EDX
+#define ASM_X86_REG_ARG_4 ASM_X86_REG_EBX
+#define ASM_X86_REG_ARG_5 ASM_X86_REG_ESI
// condition codes, used for jcc and setcc (despite their j-name!)
#define ASM_X86_CC_JB (0x2) // below, unsigned
@@ -79,9 +81,13 @@ asm_x86_t* asm_x86_new(mp_uint_t max_num_labels);
void asm_x86_free(asm_x86_t* as, bool free_code);
void asm_x86_start_pass(asm_x86_t *as, mp_uint_t pass);
void asm_x86_end_pass(asm_x86_t *as);
+mp_uint_t asm_x86_get_code_pos(asm_x86_t *as);
mp_uint_t asm_x86_get_code_size(asm_x86_t* as);
void* asm_x86_get_code(asm_x86_t* as);
+void asm_x86_align(asm_x86_t *as, mp_uint_t align);
+void asm_x86_data(asm_x86_t *as, mp_uint_t bytesize, mp_uint_t val);
+
void asm_x86_mov_r32_r32(asm_x86_t* as, int dest_r32, int src_r32);
void asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32);
void asm_x86_mov_i32_to_r32_aligned(asm_x86_t *as, int32_t src_i32, int dest_r32);
diff --git a/py/bc.c b/py/bc.c
index 865065ab19..613cce7956 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -78,8 +78,13 @@ STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) {
#define dump_args(...) (void)0
#endif
-// code_state should have ->ip filled in (pointing past code info block),
-// as well as ->n_state.
+// On entry code_state should be allocated somewhere (stack/heap) and
+// contain the following valid entries:
+// - code_state->code_info should be the offset in bytes from the start of
+// the bytecode chunk to the start of the code-info within the bytecode
+// - code_state->ip should contain the offset in bytes from the start of
+// the bytecode chunk to the start of the prelude within the bytecode
+// - code_state->n_state should be set to the state size (locals plus stack)
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
// usage for the common case of positional only args.
@@ -89,7 +94,7 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
#if MICROPY_STACKLESS
code_state->prev = NULL;
#endif
- code_state->code_info = self->bytecode;
+ code_state->code_info = self->bytecode + (mp_uint_t)code_state->code_info;
code_state->sp = &code_state->state[0] - 1;
code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1;
@@ -227,7 +232,7 @@ continue2:;
}
// bytecode prelude: initialise closed over variables
- const byte *ip = code_state->ip;
+ const byte *ip = self->bytecode + (mp_uint_t)code_state->ip;
mp_uint_t local_num;
while ((local_num = *ip++) != 255) {
code_state->state[n_state - 1 - local_num] =
diff --git a/py/emitglue.c b/py/emitglue.c
index b3e8495d94..610e76d534 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -86,16 +86,17 @@ void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len,
}
#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
-void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, mp_uint_t n_args, mp_uint_t type_sig) {
+void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_uint_t scope_flags, mp_uint_t type_sig) {
assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM);
rc->kind = kind;
- rc->scope_flags = 0;
- rc->n_pos_args = n_args;
+ rc->scope_flags = scope_flags;
+ rc->n_pos_args = n_pos_args;
+ rc->n_kwonly_args = n_kwonly_args;
rc->data.u_native.fun_data = fun_data;
rc->data.u_native.type_sig = type_sig;
#ifdef DEBUG_PRINT
- DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " n_args=" UINT_FMT "\n", kind, fun_data, fun_len, n_args);
+ DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " n_kwonly_args=" UINT_FMT " flags=%x\n", kind, fun_data, fun_len, n_pos_args, n_kwonly_args, (uint)scope_flags);
for (mp_uint_t i = 0; i < fun_len; i++) {
if (i > 0 && i % 16 == 0) {
DEBUG_printf("\n");
@@ -134,7 +135,7 @@ mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp
break;
#if MICROPY_EMIT_NATIVE
case MP_CODE_NATIVE_PY:
- fun = mp_obj_new_fun_native(rc->n_pos_args, rc->data.u_native.fun_data);
+ fun = mp_obj_new_fun_native(rc->scope_flags, rc->n_pos_args, rc->n_kwonly_args, def_args, def_kw_args, rc->data.u_native.fun_data);
break;
case MP_CODE_NATIVE_VIPER:
fun = mp_obj_new_fun_viper(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
diff --git a/py/emitglue.h b/py/emitglue.h
index 4e915df2d5..97e680b4c4 100644
--- a/py/emitglue.h
+++ b/py/emitglue.h
@@ -44,7 +44,7 @@ typedef struct _mp_raw_code_t mp_raw_code_t;
mp_raw_code_t *mp_emit_glue_new_raw_code(void);
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_uint_t scope_flags);
-void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, mp_uint_t n_args, mp_uint_t type_sig);
+void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_uint_t scope_flags, mp_uint_t type_sig);
mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args);
mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args);
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 220ff12c71..59cdc3aca6 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -90,7 +90,7 @@ STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
if (emit->pass == MP_PASS_EMIT) {
void *f = asm_thumb_get_code(emit->as);
- mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f, asm_thumb_get_code_size(emit->as), emit->scope->num_pos_args, 0);
+ mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f, asm_thumb_get_code_size(emit->as), emit->scope->num_pos_args, 0, 0, 0);
}
}
diff --git a/py/emitnative.c b/py/emitnative.c
index f72112ba07..ff57ef1a36 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -48,6 +48,7 @@
#include "py/nlr.h"
#include "py/emit.h"
+#include "py/bc.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
@@ -70,11 +71,14 @@
#define EXPORT_FUN(name) emit_native_x64_##name
+#define ASM_WORD_SIZE (8)
+
#define REG_RET ASM_X64_REG_RAX
#define REG_ARG_1 ASM_X64_REG_RDI
#define REG_ARG_2 ASM_X64_REG_RSI
#define REG_ARG_3 ASM_X64_REG_RDX
#define REG_ARG_4 ASM_X64_REG_RCX
+#define REG_ARG_5 ASM_X64_REG_R08
// caller-save
#define REG_TEMP0 ASM_X64_REG_RAX
@@ -94,12 +98,16 @@
#define ASM_NEW asm_x64_new
#define ASM_FREE asm_x64_free
#define ASM_GET_CODE asm_x64_get_code
+#define ASM_GET_CODE_POS asm_x64_get_code_pos
#define ASM_GET_CODE_SIZE asm_x64_get_code_size
#define ASM_START_PASS asm_x64_start_pass
#define ASM_END_PASS asm_x64_end_pass
#define ASM_ENTRY asm_x64_entry
#define ASM_EXIT asm_x64_exit
+#define ASM_ALIGN asm_x64_align
+#define ASM_DATA asm_x64_data
+
#define ASM_LABEL_ASSIGN asm_x64_label_assign
#define ASM_JUMP asm_x64_jmp_label
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
@@ -202,14 +210,19 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
[MP_F_DELETE_GLOBAL] = 1,
[MP_F_NEW_CELL] = 1,
[MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3,
+ [MP_F_SETUP_CODE_STATE] = 5,
};
#define EXPORT_FUN(name) emit_native_x86_##name
+#define ASM_WORD_SIZE (4)
+
#define REG_RET ASM_X86_REG_EAX
#define REG_ARG_1 ASM_X86_REG_ARG_1
#define REG_ARG_2 ASM_X86_REG_ARG_2
#define REG_ARG_3 ASM_X86_REG_ARG_3
+#define REG_ARG_4 ASM_X86_REG_ARG_4
+#define REG_ARG_5 ASM_X86_REG_ARG_5
// caller-save, so can be used as temporaries
#define REG_TEMP0 ASM_X86_REG_EAX
@@ -229,12 +242,16 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
#define ASM_NEW asm_x86_new
#define ASM_FREE asm_x86_free
#define ASM_GET_CODE asm_x86_get_code
+#define ASM_GET_CODE_POS asm_x86_get_code_pos
#define ASM_GET_CODE_SIZE asm_x86_get_code_size
#define ASM_START_PASS asm_x86_start_pass
#define ASM_END_PASS asm_x86_end_pass
#define ASM_ENTRY asm_x86_entry
#define ASM_EXIT asm_x86_exit
+#define ASM_ALIGN asm_x86_align
+#define ASM_DATA asm_x86_data
+
#define ASM_LABEL_ASSIGN asm_x86_label_assign
#define ASM_JUMP asm_x86_jmp_label
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
@@ -292,11 +309,14 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
#define EXPORT_FUN(name) emit_native_thumb_##name
+#define ASM_WORD_SIZE (4)
+
#define REG_RET ASM_THUMB_REG_R0
#define REG_ARG_1 ASM_THUMB_REG_R0
#define REG_ARG_2 ASM_THUMB_REG_R1
#define REG_ARG_3 ASM_THUMB_REG_R2
#define REG_ARG_4 ASM_THUMB_REG_R3
+// rest of args go on stack
#define REG_TEMP0 ASM_THUMB_REG_R0
#define REG_TEMP1 ASM_THUMB_REG_R1
@@ -314,12 +334,16 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
#define ASM_NEW asm_thumb_new
#define ASM_FREE asm_thumb_free
#define ASM_GET_CODE asm_thumb_get_code
+#define ASM_GET_CODE_POS asm_thumb_get_code_pos
#define ASM_GET_CODE_SIZE asm_thumb_get_code_size
#define ASM_START_PASS asm_thumb_start_pass
#define ASM_END_PASS asm_thumb_end_pass
#define ASM_ENTRY asm_thumb_entry
#define ASM_EXIT asm_thumb_exit
+#define ASM_ALIGN asm_thumb_align
+#define ASM_DATA asm_thumb_data
+
#define ASM_LABEL_ASSIGN asm_thumb_label_assign
#define ASM_JUMP asm_thumb_b_label
#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
@@ -504,6 +528,10 @@ struct _emit_t {
stack_info_t *stack_info;
vtype_kind_t saved_stack_vtype;
+ int code_info_size;
+ int code_info_offset;
+ int prelude_offset;
+ int n_state;
int stack_start;
int stack_size;
@@ -561,6 +589,8 @@ STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg);
STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num);
STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num);
+#define STATE_START (sizeof(mp_code_state) / sizeof(mp_uint_t))
+
STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
@@ -584,14 +614,23 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc);
}
- // set default type for return and arguments
+ // set default type for return
emit->return_vtype = VTYPE_PYOBJ;
- for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) {
+
+ // set default type for arguments
+ mp_uint_t num_args = emit->scope->num_pos_args + emit->scope->num_kwonly_args;
+ if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {
+ num_args += 1;
+ }
+ if (scope->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) {
+ num_args += 1;
+ }
+ for (mp_uint_t i = 0; i < num_args; i++) {
emit->local_vtype[i] = VTYPE_PYOBJ;
}
// local variables begin unbound, and have unknown type
- for (mp_uint_t i = emit->scope->num_pos_args; i < emit->local_vtype_alloc; i++) {
+ for (mp_uint_t i = num_args; i < emit->local_vtype_alloc; i++) {
emit->local_vtype[i] = VTYPE_UNBOUND;
}
@@ -603,107 +642,157 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
ASM_START_PASS(emit->as, pass == MP_PASS_EMIT ? ASM_PASS_EMIT : ASM_PASS_COMPUTE);
- // entry to function
- int num_locals = 0;
- if (pass > MP_PASS_SCOPE) {
- num_locals = scope->num_locals - REG_LOCAL_NUM;
- if (num_locals < 0) {
- num_locals = 0;
- }
- emit->stack_start = num_locals;
- num_locals += scope->stack_size;
- }
- ASM_ENTRY(emit->as, num_locals);
+ // generate code for entry to function
- // initialise locals from parameters
-#if N_X64
- for (int i = 0; i < scope->num_pos_args; i++) {
- if (i == 0) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_1, REG_ARG_1);
- } else if (i == 1) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_2, REG_ARG_2);
- } else if (i == 2) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);
- } else if (i == 3) {
- asm_x64_mov_r64_to_local(emit->as, REG_ARG_4, i - REG_LOCAL_NUM);
- } else {
- // TODO not implemented
- assert(0);
+ if (emit->do_viper_types) {
+
+ // entry to function
+ int num_locals = 0;
+ if (pass > MP_PASS_SCOPE) {
+ num_locals = scope->num_locals - REG_LOCAL_NUM;
+ if (num_locals < 0) {
+ num_locals = 0;
+ }
+ emit->stack_start = num_locals;
+ num_locals += scope->stack_size;
}
- }
-#elif N_X86
- for (int i = 0; i < scope->num_pos_args; i++) {
- if (i == 0) {
- asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_1);
- } else if (i == 1) {
- asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_2);
- } else if (i == 2) {
- asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_3);
- } else {
- asm_x86_mov_arg_to_r32(emit->as, i, REG_TEMP0);
- asm_x86_mov_r32_to_local(emit->as, REG_TEMP0, i - REG_LOCAL_NUM);
+ ASM_ENTRY(emit->as, num_locals);
+
+ #if N_X86
+ for (int i = 0; i < scope->num_pos_args; i++) {
+ if (i == 0) {
+ asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_1);
+ } else if (i == 1) {
+ asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_2);
+ } else if (i == 2) {
+ asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_3);
+ } else {
+ asm_x86_mov_arg_to_r32(emit->as, i, REG_TEMP0);
+ asm_x86_mov_r32_to_local(emit->as, REG_TEMP0, i - REG_LOCAL_NUM);
+ }
}
- }
-#elif N_THUMB
- for (int i = 0; i < scope->num_pos_args; i++) {
- if (i == 0) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_1, REG_ARG_1);
- } else if (i == 1) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_2, REG_ARG_2);
- } else if (i == 2) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);
- } else if (i == 3) {
- asm_thumb_mov_local_reg(emit->as, i - REG_LOCAL_NUM, REG_ARG_4);
- } else {
- // TODO not implemented
- assert(0);
+ #else
+ for (int i = 0; i < scope->num_pos_args; i++) {
+ if (i == 0) {
+ ASM_MOV_REG_REG(emit->as, REG_LOCAL_1, REG_ARG_1);
+ } else if (i == 1) {
+ ASM_MOV_REG_REG(emit->as, REG_LOCAL_2, REG_ARG_2);
+ } else if (i == 2) {
+ ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);
+ } else if (i == 3) {
+ ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_4, i - REG_LOCAL_NUM);
+ } else {
+ // TODO not implemented
+ assert(0);
+ }
+ }
+ #endif
+
+ } else {
+ // work out size of state (locals plus stack)
+ emit->n_state = scope->num_locals + scope->stack_size;
+
+ // allocate space on C-stack for code_state structure, which includes state
+ ASM_ENTRY(emit->as, STATE_START + emit->n_state);
+
+ // prepare incoming arguments for call to mp_setup_code_state
+ #if N_X86
+ asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_2);
+ asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_3);
+ asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_4);
+ asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_5);
+ #else
+ #if N_THUMB
+ ASM_MOV_REG_REG(emit->as, ASM_THUMB_REG_R4, REG_ARG_4);
+ #else
+ ASM_MOV_REG_REG(emit->as, REG_ARG_5, REG_ARG_4);
+ #endif
+ ASM_MOV_REG_REG(emit->as, REG_ARG_4, REG_ARG_3);
+ ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_ARG_2);
+ ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_ARG_1);
+ #endif
+
+ // set code_state.code_info (offset from start of this function to code_info data)
+ // XXX this encoding may change size
+ ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->code_info_offset, offsetof(mp_code_state, code_info) / sizeof(mp_uint_t), REG_ARG_1);
+
+ // set code_state.ip (offset from start of this function to prelude info)
+ // XXX this encoding may change size
+ ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state, ip) / sizeof(mp_uint_t), REG_ARG_1);
+
+ // set code_state.n_state
+ ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state, n_state) / sizeof(mp_uint_t), REG_ARG_1);
+
+ // put address of code_state into first arg
+ ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1);
+
+ // call mp_setup_code_state to prepare code_state structure
+ #if N_THUMB
+ asm_thumb_op16(emit->as, 0xb400 | (1 << ASM_THUMB_REG_R4)); // push 5th arg
+ asm_thumb_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4);
+ asm_thumb_op16(emit->as, 0xbc00 | (1 << REG_RET)); // pop dummy (was 5th arg)
+ #else
+ ASM_CALL_IND(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE);
+ #endif
+
+ // cache some locals in registers
+ if (scope->num_locals > 0) {
+ ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 0, REG_LOCAL_1);
+ if (scope->num_locals > 1) {
+ ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 1, REG_LOCAL_2);
+ if (scope->num_locals > 2) {
+ ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 2, REG_LOCAL_3);
+ }
+ }
+ }
+
+ // set the type of closed over variables
+ for (mp_uint_t i = 0; i < scope->id_info_len; i++) {
+ id_info_t *id = &scope->id_info[i];
+ if (id->kind == ID_INFO_KIND_CELL) {
+ emit->local_vtype[id->local_num] = VTYPE_PYOBJ;
+ }
}
}
+ #if N_THUMB
// 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++) {
- if (i == 0) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_1, REG_ARG_1);
- } else if (i == 1) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_2, REG_ARG_2);
- } else if (i == 2) {
- ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);
- } else if (i == 3) {
- asm_arm_mov_local_reg(emit->as, i - REG_LOCAL_NUM, REG_ARG_4);
- } else {
- // TODO not implemented
- assert(0);
- }
- }
+ #endif
+ #if N_ARM
// 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
-#endif
-
- // initialise closed over variables
- for (int i = 0; i < scope->id_info_len; i++) {
- id_info_t *id = &scope->id_info[i];
- if (id->kind == ID_INFO_KIND_CELL) {
- if (emit->local_vtype[id->local_num] != VTYPE_UNBOUND) {
- emit_native_load_fast(emit, id->qst, id->local_num);
- vtype_kind_t vtype;
- emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
- }
- ASM_CALL_IND(emit->as, mp_fun_table[MP_F_NEW_CELL], MP_F_NEW_CELL);
- emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
- emit_native_store_fast(emit, id->qst, id->local_num);
- }
- }
+ #endif
}
STATIC void emit_native_end_pass(emit_t *emit) {
if (!emit->last_emit_was_return_value) {
ASM_EXIT(emit->as);
}
+
+ if (!emit->do_viper_types) {
+ // write dummy code info (for mp_setup_code_state to parse) and arg names
+ emit->code_info_offset = ASM_GET_CODE_POS(emit->as);
+ ASM_DATA(emit->as, 1, emit->code_info_size);
+ ASM_ALIGN(emit->as, ASM_WORD_SIZE);
+ emit->code_info_size = ASM_GET_CODE_POS(emit->as) - emit->code_info_offset;
+ for (int i = 0; i < emit->scope->num_pos_args + emit->scope->num_kwonly_args; i++) {
+ ASM_DATA(emit->as, ASM_WORD_SIZE, (mp_uint_t)MP_OBJ_NEW_QSTR(emit->scope->id_info[i].qst));
+ }
+
+ // bytecode prelude: initialise closed over variables
+ emit->prelude_offset = ASM_GET_CODE_POS(emit->as);
+ for (int i = 0; i < emit->scope->id_info_len; i++) {
+ id_info_t *id = &emit->scope->id_info[i];
+ if (id->kind == ID_INFO_KIND_CELL) {
+ assert(id->local_num < 255);
+ ASM_DATA(emit->as, 1, id->local_num); // write the local which should be converted to a cell
+ }
+ }
+ ASM_DATA(emit->as, 1, 255); // end of list sentinel
+ }
+
ASM_END_PASS(emit->as);
// check stack is back to zero size
@@ -722,7 +811,10 @@ STATIC void emit_native_end_pass(emit_t *emit) {
type_sig |= (emit->local_vtype[i] & 3) << (i * 2 + 2);
}
- mp_emit_glue_assign_native(emit->scope->raw_code, emit->do_viper_types ? MP_CODE_NATIVE_VIPER : MP_CODE_NATIVE_PY, f, f_len, emit->scope->num_pos_args, type_sig);
+ mp_emit_glue_assign_native(emit->scope->raw_code,
+ emit->do_viper_types ? MP_CODE_NATIVE_VIPER : MP_CODE_NATIVE_PY,
+ f, f_len, emit->scope->num_pos_args, emit->scope->num_kwonly_args,
+ emit->scope->scope_flags, type_sig);
}
}
@@ -1199,43 +1291,6 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
printf("ViperTypeError: local %s used before type known\n", qstr_str(qst));
}
emit_native_pre(emit);
-#if N_X64
- if (local_num == 0) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_1);
- } else if (local_num == 1) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_2);
- } else if (local_num == 2) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_3);
- } else {
- need_reg_single(emit, REG_TEMP0, 0);
- asm_x64_mov_local_to_r64(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
- emit_post_push_reg(emit, vtype, REG_TEMP0);
- }
-#elif N_X86
- if (local_num == 0) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_1);
- } else if (local_num == 1) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_2);
- } else if (local_num == 2) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_3);
- } else {
- need_reg_single(emit, REG_TEMP0, 0);
- asm_x86_mov_local_to_r32(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
- emit_post_push_reg(emit, vtype, REG_TEMP0);
- }
-#elif N_THUMB
- if (local_num == 0) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_1);
- } else if (local_num == 1) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_2);
- } else if (local_num == 2) {
- emit_post_push_reg(emit, vtype, REG_LOCAL_3);
- } else {
- need_reg_single(emit, REG_TEMP0, 0);
- asm_thumb_mov_reg_local(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
- emit_post_push_reg(emit, vtype, REG_TEMP0);
- }
-#elif N_ARM
if (local_num == 0) {
emit_post_push_reg(emit, vtype, REG_LOCAL_1);
} else if (local_num == 1) {
@@ -1244,12 +1299,13 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
emit_post_push_reg(emit, vtype, REG_LOCAL_3);
} else {
need_reg_single(emit, REG_TEMP0, 0);
- asm_arm_mov_reg_local(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
+ if (emit->do_viper_types) {
+ ASM_MOV_LOCAL_TO_REG(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
+ } else {
+ ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - local_num, REG_TEMP0);
+ }
emit_post_push_reg(emit, vtype, REG_TEMP0);
}
-#else
- #error not implemented
-#endif
}
STATIC void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
@@ -1417,40 +1473,6 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
vtype_kind_t vtype;
-#if N_X64
- if (local_num == 0) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
- } else if (local_num == 1) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
- } else if (local_num == 2) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
- } else {
- emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
- asm_x64_mov_r64_to_local(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
- }
-#elif N_X86
- if (local_num == 0) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
- } else if (local_num == 1) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
- } else if (local_num == 2) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
- } else {
- emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
- asm_x86_mov_r32_to_local(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
- }
-#elif N_THUMB
- if (local_num == 0) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
- } else if (local_num == 1) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
- } else if (local_num == 2) {
- emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
- } else {
- emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
- asm_thumb_mov_local_reg(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
- }
-#elif N_ARM
if (local_num == 0) {
emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
} else if (local_num == 1) {
@@ -1459,12 +1481,12 @@ STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num)
emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
} else {
emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
- asm_arm_mov_local_reg(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
+ if (emit->do_viper_types) {
+ ASM_MOV_REG_TO_LOCAL(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
+ } else {
+ ASM_MOV_REG_TO_LOCAL(emit->as, REG_TEMP0, STATE_START + emit->n_state - 1 - local_num);
+ }
}
-#else
- #error not implemented
-#endif
-
emit_post(emit);
// check types
diff --git a/py/nativeglue.c b/py/nativeglue.c
index ab4063014c..d0896eedd3 100644
--- a/py/nativeglue.c
+++ b/py/nativeglue.c
@@ -32,6 +32,7 @@
#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/emitglue.h"
+#include "py/bc.h"
#if MICROPY_EMIT_NATIVE
@@ -135,6 +136,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_delete_global,
mp_obj_new_cell,
mp_make_closure_from_raw_code,
+ mp_setup_code_state,
};
/*
diff --git a/py/obj.h b/py/obj.h
index b1f173080d..448db762af 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -469,7 +469,7 @@ mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, mp_uint_t n_ar
mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg);
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!)
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code);
-mp_obj_t mp_obj_new_fun_native(mp_uint_t n_args, void *fun_data);
+mp_obj_t mp_obj_new_fun_native(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data);
mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig);
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data);
mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun);
diff --git a/py/objfun.c b/py/objfun.c
index 25a835e9b5..48c51053df 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -108,8 +108,18 @@ qstr mp_obj_code_get_name(const byte *code_info) {
return mp_decode_uint(&code_info);
}
+#if MICROPY_EMIT_NATIVE
+STATIC const mp_obj_type_t mp_type_fun_native;
+#endif
+
qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
const mp_obj_fun_bc_t *fun = fun_in;
+ #if MICROPY_EMIT_NATIVE
+ if (fun->base.type == &mp_type_fun_native) {
+ // TODO native functions don't have name stored
+ return MP_QSTR_;
+ }
+ #endif
const byte *code_info = fun->bytecode;
return mp_obj_code_get_name(code_info);
}
@@ -168,7 +178,8 @@ mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, mp_uint_t n_arg
}
code_state->n_state = n_state;
- code_state->ip = ip;
+ code_state->code_info = 0; // offset to code-info
+ code_state->ip = ip - self->bytecode; // offset to prelude
mp_setup_code_state(code_state, self_in, n_args, n_kw, args);
// execute the byte code with the correct globals context
@@ -216,7 +227,8 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
}
code_state->n_state = n_state;
- code_state->ip = ip;
+ code_state->code_info = 0; // offset to code-info
+ code_state->ip = (byte*)(ip - self->bytecode); // offset to prelude
mp_setup_code_state(code_state, self_in, n_args, n_kw, args);
// execute the byte code with the correct globals context
@@ -339,42 +351,11 @@ mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_
#if MICROPY_EMIT_NATIVE
-typedef struct _mp_obj_fun_native_t {
- mp_obj_base_t base;
- mp_uint_t n_args;
- void *fun_data; // GC must be able to trace this pointer
- // TODO add mp_map_t *globals
-} mp_obj_fun_native_t;
-
-typedef mp_obj_t (*native_fun_0_t)(void);
-typedef mp_obj_t (*native_fun_1_t)(mp_obj_t);
-typedef mp_obj_t (*native_fun_2_t)(mp_obj_t, mp_obj_t);
-typedef mp_obj_t (*native_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t);
-
STATIC mp_obj_t fun_native_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
- mp_obj_fun_native_t *self = self_in;
-
- mp_arg_check_num(n_args, n_kw, self->n_args, self->n_args, false);
-
- void *fun = MICROPY_MAKE_POINTER_CALLABLE(self->fun_data);
-
- switch (n_args) {
- case 0:
- return ((native_fun_0_t)fun)();
-
- case 1:
- return ((native_fun_1_t)fun)(args[0]);
-
- case 2:
- return ((native_fun_2_t)fun)(args[0], args[1]);
-
- case 3:
- return ((native_fun_3_t)fun)(args[0], args[1], args[2]);
-
- default:
- assert(0);
- return mp_const_none;
- }
+ MP_STACK_CHECK();
+ mp_obj_fun_bc_t *self = self_in;
+ mp_call_fun_t fun = MICROPY_MAKE_POINTER_CALLABLE((void*)self->bytecode);
+ return fun(self_in, n_args, n_kw, args);
}
STATIC const mp_obj_type_t mp_type_fun_native = {
@@ -383,12 +364,9 @@ STATIC const mp_obj_type_t mp_type_fun_native = {
.call = fun_native_call,
};
-mp_obj_t mp_obj_new_fun_native(mp_uint_t n_args, void *fun_data) {
- assert(0 <= n_args && n_args <= 3);
- mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t);
+mp_obj_t mp_obj_new_fun_native(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data) {
+ mp_obj_fun_bc_t *o = mp_obj_new_fun_bc(scope_flags, n_pos_args, n_kwonly_args, def_args_in, def_kw_args, (const byte*)fun_data);
o->base.type = &mp_type_fun_native;
- o->n_args = n_args;
- o->fun_data = fun_data;
return o;
}
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 112becb46b..f672b8d99d 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -73,7 +73,8 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw
o->globals = self_fun->globals;
o->code_state.n_state = n_state;
- o->code_state.ip = ip;
+ o->code_state.code_info = 0; // offset to code-info
+ o->code_state.ip = (byte*)(ip - self_fun->bytecode); // offset to prelude
mp_setup_code_state(&o->code_state, self_fun, n_args, n_kw, args);
return o;
}
diff --git a/py/runtime0.h b/py/runtime0.h
index 7ee8c9aa49..be9fc8d524 100644
--- a/py/runtime0.h
+++ b/py/runtime0.h
@@ -151,6 +151,7 @@ typedef enum {
MP_F_DELETE_GLOBAL,
MP_F_NEW_CELL,
MP_F_MAKE_CLOSURE_FROM_RAW_CODE,
+ MP_F_SETUP_CODE_STATE,
MP_F_NUMBER_OF,
} mp_fun_kind_t;
diff --git a/tests/run-tests b/tests/run-tests
index c64d347e8f..ebe295c7df 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -154,19 +154,22 @@ def run_tests(pyb, tests, args):
# Some tests are known to fail with native emitter
# Remove them from the below when they work
if args.emit == 'native':
- skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class closure_defargs del_deref del_local fun3 fun_calldblstar fun_callstar fun_callstardblstar fun_defargs fun_defargs2 fun_kwargs fun_kwonly fun_kwonlydef fun_kwvarargs fun_varargs gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_throw generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send globals_del string_format string_join subclass_native2_list subclass_native2_tuple try_finally_loops try_finally_return try_reraise try_reraise2 unboundlocal with1 with_break with_continue with_return'.split()})
+ skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_throw generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send'.split()}) # require yield
+ skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class globals_del string_join'.split()}) # require yield
+ skip_tests.update({'basics/%s.py' % t for t in 'try_reraise try_reraise2'.split()}) # require raise_varargs
+ skip_tests.update({'basics/%s.py' % t for t in 'with1 with_break with_continue with_return'.split()}) # require with
skip_tests.add('basics/array_construct2.py') # requires generators
skip_tests.add('basics/bool1.py') # seems to randomly fail
- skip_tests.add('basics/boundmeth1.py') # requires support for many args
- skip_tests.add('basics/closure_manyvars.py') # requires closures
- skip_tests.add('float/string_format.py')
- skip_tests.add('import/gen_context.py')
- skip_tests.add('io/file_with.py')
- skip_tests.add('io/stringio_with.py')
- skip_tests.add('micropython/heapalloc.py')
- skip_tests.add('misc/features.py')
- skip_tests.add('misc/recursion.py')
- skip_tests.add('misc/rge_sm.py')
+ skip_tests.add('basics/del_deref.py') # requires checking for unbound local
+ skip_tests.add('basics/del_local.py') # requires checking for unbound local
+ skip_tests.add('basics/try_finally_loops.py') # requires proper try finally code
+ skip_tests.add('basics/try_finally_return.py') # requires proper try finally code
+ skip_tests.add('basics/unboundlocal.py') # requires checking for unbound local
+ skip_tests.add('import/gen_context.py') # requires yield_value
+ skip_tests.add('io/file_with.py') # requires with
+ skip_tests.add('io/stringio_with.py') # requires with
+ skip_tests.add('misc/features.py') # requires raise_varargs
+ skip_tests.add('misc/rge_sm.py') # requires yield
skip_tests.add('misc/print_exception.py') # because native doesn't have proper traceback info
for test_file in tests: