diff options
Diffstat (limited to 'py')
| -rw-r--r-- | py/argcheck.c | 2 | ||||
| -rw-r--r-- | py/bc.c | 6 | ||||
| -rw-r--r-- | py/bc0.h | 4 | ||||
| -rw-r--r-- | py/emitnative.c | 43 | ||||
| -rw-r--r-- | py/formatfloat.c | 13 | ||||
| -rw-r--r-- | py/makeqstrdata.py | 10 | ||||
| -rw-r--r-- | py/mkenv.mk | 6 | ||||
| -rw-r--r-- | py/mkrules.mk | 6 | ||||
| -rw-r--r-- | py/modbuiltins.c | 25 | ||||
| -rw-r--r-- | py/modmath.c | 73 | ||||
| -rw-r--r-- | py/mpconfig.h | 22 | ||||
| -rw-r--r-- | py/mpstate.h | 2 | ||||
| -rw-r--r-- | py/nativeglue.c | 3 | ||||
| -rw-r--r-- | py/objarray.c | 2 | ||||
| -rw-r--r-- | py/objlist.c | 4 | ||||
| -rw-r--r-- | py/objtype.c | 98 | ||||
| -rw-r--r-- | py/persistentcode.c | 2 | ||||
| -rw-r--r-- | py/runtime.c | 7 | ||||
| -rw-r--r-- | py/runtime.h | 4 | ||||
| -rw-r--r-- | py/runtime0.h | 38 | ||||
| -rw-r--r-- | py/showbc.c | 4 | ||||
| -rw-r--r-- | py/vmentrytable.h | 4 |
22 files changed, 223 insertions, 155 deletions
diff --git a/py/argcheck.c b/py/argcheck.c index 46be126ac..2a606d613 100644 --- a/py/argcheck.c +++ b/py/argcheck.c @@ -136,11 +136,9 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, mp_arg_parse_all(n_pos, args, &kw_args, n_allowed, allowed, out_vals); } -#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || defined(_MSC_VER) NORETURN void mp_arg_error_terse_mismatch(void) { mp_raise_TypeError("argument num/types mismatch"); } -#endif #if MICROPY_CPYTHON_COMPAT NORETURN void mp_arg_error_unimpl_kw(void) { @@ -322,7 +322,7 @@ STATIC const byte opcode_format_table[64] = { OC4(O, O, U, U), // 0x38-0x3b OC4(U, O, B, O), // 0x3c-0x3f OC4(O, B, B, O), // 0x40-0x43 - OC4(B, B, O, U), // 0x44-0x47 + OC4(B, B, O, B), // 0x44-0x47 OC4(U, U, U, U), // 0x48-0x4b OC4(U, U, U, U), // 0x4c-0x4f OC4(V, V, U, V), // 0x50-0x53 @@ -362,7 +362,7 @@ STATIC const byte opcode_format_table[64] = { OC4(B, B, B, B), // 0xcc-0xcf OC4(B, B, B, B), // 0xd0-0xd3 - OC4(B, B, B, B), // 0xd4-0xd7 + OC4(U, U, U, B), // 0xd4-0xd7 OC4(B, B, B, B), // 0xd8-0xdb OC4(B, B, B, B), // 0xdc-0xdf @@ -373,7 +373,7 @@ STATIC const byte opcode_format_table[64] = { OC4(B, B, B, B), // 0xf0-0xf3 OC4(B, B, B, B), // 0xf4-0xf7 - OC4(B, B, B, U), // 0xf8-0xfb + OC4(U, U, U, U), // 0xf8-0xfb OC4(U, U, U, U), // 0xfc-0xff }; #undef OC4 @@ -113,7 +113,7 @@ #define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // + N(64) #define MP_BC_LOAD_FAST_MULTI (0xb0) // + N(16) #define MP_BC_STORE_FAST_MULTI (0xc0) // + N(16) -#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(<MP_UNARY_OP_NON_BYTECODE) -#define MP_BC_BINARY_OP_MULTI (0xd7) // + op(36) +#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(<MP_UNARY_OP_NUM_BYTECODE) +#define MP_BC_BINARY_OP_MULTI (0xd7) // + op(<MP_BINARY_OP_NUM_BYTECODE) #endif // MICROPY_INCLUDED_PY_BC0_H diff --git a/py/emitnative.c b/py/emitnative.c index b2c9a7366..8e97dda11 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -123,6 +123,8 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_NEW_CELL] = 1, [MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3, [MP_F_SETUP_CODE_STATE] = 5, + [MP_F_SMALL_INT_FLOOR_DIVIDE] = 2, + [MP_F_SMALL_INT_MODULO] = 2, }; #include "py/asmx86.h" @@ -1823,18 +1825,20 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { vtype_kind_t vtype_lhs = peek_vtype(emit, 1); vtype_kind_t vtype_rhs = peek_vtype(emit, 0); if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) { + // for integers, inplace and normal ops are equivalent, so use just normal ops + if (MP_BINARY_OP_INPLACE_OR <= op && op <= MP_BINARY_OP_INPLACE_POWER) { + op += MP_BINARY_OP_OR - MP_BINARY_OP_INPLACE_OR; + } + #if N_X64 || N_X86 // special cases for x86 and shifting - if (op == MP_BINARY_OP_LSHIFT - || op == MP_BINARY_OP_INPLACE_LSHIFT - || op == MP_BINARY_OP_RSHIFT - || op == MP_BINARY_OP_INPLACE_RSHIFT) { + if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_RSHIFT) { #if N_X64 emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X64_REG_RCX, &vtype_lhs, REG_RET); #else emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X86_REG_ECX, &vtype_lhs, REG_RET); #endif - if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) { + if (op == MP_BINARY_OP_LSHIFT) { ASM_LSL_REG(emit->as, REG_RET); } else { ASM_ASR_REG(emit->as, REG_RET); @@ -1843,35 +1847,48 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { return; } #endif + + // special cases for floor-divide and module because we dispatch to helper functions + if (op == MP_BINARY_OP_FLOOR_DIVIDE || op == MP_BINARY_OP_MODULO) { + emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_2, &vtype_lhs, REG_ARG_1); + if (op == MP_BINARY_OP_FLOOR_DIVIDE) { + emit_call(emit, MP_F_SMALL_INT_FLOOR_DIVIDE); + } else { + emit_call(emit, MP_F_SMALL_INT_MODULO); + } + emit_post_push_reg(emit, VTYPE_INT, REG_RET); + return; + } + int reg_rhs = REG_ARG_3; 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 #if !(N_X64 || N_X86) - } else if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) { + } else if (op == MP_BINARY_OP_LSHIFT) { ASM_LSL_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); - } else if (op == MP_BINARY_OP_RSHIFT || op == MP_BINARY_OP_INPLACE_RSHIFT) { + } else if (op == MP_BINARY_OP_RSHIFT) { ASM_ASR_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); #endif - } else if (op == MP_BINARY_OP_OR || op == MP_BINARY_OP_INPLACE_OR) { + } else if (op == MP_BINARY_OP_OR) { ASM_OR_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); - } else if (op == MP_BINARY_OP_XOR || op == MP_BINARY_OP_INPLACE_XOR) { + } else if (op == MP_BINARY_OP_XOR) { ASM_XOR_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); - } else if (op == MP_BINARY_OP_AND || op == MP_BINARY_OP_INPLACE_AND) { + } else if (op == MP_BINARY_OP_AND) { ASM_AND_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); - } else if (op == MP_BINARY_OP_ADD || op == MP_BINARY_OP_INPLACE_ADD) { + } else if (op == MP_BINARY_OP_ADD) { ASM_ADD_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); - } else if (op == MP_BINARY_OP_SUBTRACT || op == MP_BINARY_OP_INPLACE_SUBTRACT) { + } else if (op == MP_BINARY_OP_SUBTRACT) { ASM_SUB_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); - } else if (op == MP_BINARY_OP_MULTIPLY || op == MP_BINARY_OP_INPLACE_MULTIPLY) { + } else if (op == MP_BINARY_OP_MULTIPLY) { ASM_MUL_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (MP_BINARY_OP_LESS <= op && op <= MP_BINARY_OP_NOT_EQUAL) { diff --git a/py/formatfloat.c b/py/formatfloat.c index 35cd5d51a..4228f99ff 100644 --- a/py/formatfloat.c +++ b/py/formatfloat.c @@ -30,6 +30,7 @@ #include <assert.h> #include <stdlib.h> #include <stdint.h> +#include <math.h> #include "py/formatfloat.h" /*********************************************************************** @@ -68,12 +69,10 @@ union floatbits { uint32_t u; }; static inline int fp_signbit(float x) { union floatbits fb = {x}; return fb.u & FLT_SIGN_MASK; } -static inline int fp_isspecial(float x) { union floatbits fb = {x}; return (fb.u & FLT_EXP_MASK) == FLT_EXP_MASK; } -static inline int fp_isinf(float x) { union floatbits fb = {x}; return (fb.u & FLT_MAN_MASK) == 0; } +#define fp_isnan(x) isnan(x) +#define fp_isinf(x) isinf(x) static inline int fp_iszero(float x) { union floatbits fb = {x}; return fb.u == 0; } static inline int fp_isless1(float x) { union floatbits fb = {x}; return fb.u < 0x3f800000; } -// Assumes both fp_isspecial() and fp_isinf() were applied before -#define fp_isnan(x) 1 #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE @@ -82,9 +81,7 @@ static inline int fp_isless1(float x) { union floatbits fb = {x}; return fb.u < #define FPROUND_TO_ONE 0.999999999995 #define FPDECEXP 256 #define FPMIN_BUF_SIZE 7 // +9e+199 -#include <math.h> #define fp_signbit(x) signbit(x) -#define fp_isspecial(x) 1 #define fp_isnan(x) isnan(x) #define fp_isinf(x) isinf(x) #define fp_iszero(x) (x == 0) @@ -122,7 +119,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } return buf_size >= 2; } - if (fp_signbit(f)) { + if (fp_signbit(f) && !fp_isnan(f)) { *s++ = '-'; f = -f; } else { @@ -135,7 +132,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch // It is buf_size minus room for the sign and null byte. int buf_remaining = buf_size - 1 - (s - buf); - if (fp_isspecial(f)) { + { char uc = fmt & 0x20; if (fp_isinf(f)) { *s++ = 'I' ^ uc; diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 7249769f4..38fde1a9c 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -108,7 +108,15 @@ def parse_input_headers(infiles): continue # add the qstr to the list, with order number to retain original order in file - qstrs[ident] = (len(qstrs), ident, qstr) + order = len(qstrs) + # but put special method names like __add__ at the top of list, so + # that their id's fit into a byte + if ident == "": + # Sort empty qstr above all still + order = -200000 + elif ident.startswith("__"): + order -= 100000 + qstrs[ident] = (order, ident, qstr) if not qcfgs: sys.stderr.write("ERROR: Empty preprocessor output - check for errors above\n") diff --git a/py/mkenv.mk b/py/mkenv.mk index 507fa6eab..5a118854a 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -68,13 +68,7 @@ LD += -m32 endif MAKE_FROZEN = $(TOP)/tools/make-frozen.py -# allow mpy-cross (for WSL) and mpy-cross.exe (for cygwin) to coexist -ifeq ($(OS),Windows_NT) -MPY_CROSS = $(TOP)/mpy-cross/mpy-cross.exe -PROG_EXT = .exe -else MPY_CROSS = $(TOP)/mpy-cross/mpy-cross -endif MPY_TOOL = $(TOP)/tools/mpy-tool.py all: diff --git a/py/mkrules.mk b/py/mkrules.mk index e26b94939..1d6f11fc9 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -144,13 +144,13 @@ $(PROG): $(OBJ) # we may want to compile using Thumb, but link with non-Thumb libc. $(Q)$(CC) -o $@ $^ $(LIB) $(LDFLAGS) ifndef DEBUG - $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)$(PROG_EXT) + $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG) endif - $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $(PROG)$(PROG_EXT) + $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $(PROG) clean: clean-prog clean-prog: - $(RM) -f $(PROG)$(PROG_EXT) + $(RM) -f $(PROG) $(RM) -f $(PROG).map .PHONY: clean-prog diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 991feda8c..728309292 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -348,31 +348,16 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { if (MP_OBJ_IS_STR(o_in)) { len = unichar_charlen(str, len); if (len == 1) { - if (!UTF8_IS_NONASCII(*str)) { - goto return_first_byte; - } - mp_int_t ord = *str++ & 0x7F; - for (mp_int_t mask = 0x40; ord & mask; mask >>= 1) { - ord &= ~mask; - } - while (UTF8_IS_CONT(*str)) { - ord = (ord << 6) | (*str++ & 0x3F); - } - return mp_obj_new_int(ord); + return mp_obj_new_int(utf8_get_char((const byte*)str)); } - } else { - // a bytes object + } else + #endif + { + // a bytes object, or a str without unicode support (don't sign extend the char) if (len == 1) { - return_first_byte: return MP_OBJ_NEW_SMALL_INT(((const byte*)str)[0]); } } - #else - if (len == 1) { - // don't sign extend when converting to ord - return mp_obj_new_int(((const byte*)str)[0]); - } - #endif if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("ord expects a character"); diff --git a/py/modmath.c b/py/modmath.c index 909780596..56ceb14bd 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,14 +40,31 @@ STATIC NORETURN void math_error(void) { mp_raise_ValueError("math domain error"); } +STATIC mp_obj_t math_generic_1(mp_obj_t x_obj, mp_float_t (*f)(mp_float_t)) { + mp_float_t x = mp_obj_get_float(x_obj); + mp_float_t ans = f(x); + if ((isnan(ans) && !isnan(x)) || (isinf(ans) && !isinf(x))) { + math_error(); + } + return mp_obj_new_float(ans); +} + +STATIC mp_obj_t math_generic_2(mp_obj_t x_obj, mp_obj_t y_obj, mp_float_t (*f)(mp_float_t, mp_float_t)) { + mp_float_t x = mp_obj_get_float(x_obj); + mp_float_t y = mp_obj_get_float(y_obj); + mp_float_t ans = f(x, y); + if ((isnan(ans) && !isnan(x) && !isnan(y)) || (isinf(ans) && !isinf(x))) { + math_error(); + } + return mp_obj_new_float(ans); +} + #define MATH_FUN_1(py_name, c_name) \ - STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \ + STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { \ + return math_generic_1(x_obj, MICROPY_FLOAT_C_FUN(c_name)); \ + } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); -#define MATH_FUN_2(py_name, c_name) \ - STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \ - STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name); - #define MATH_FUN_1_TO_BOOL(py_name, c_name) \ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_bool(c_name(mp_obj_get_float(x_obj))); } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); @@ -56,23 +73,29 @@ STATIC NORETURN void math_error(void) { STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int_from_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); -#define MATH_FUN_1_ERRCOND(py_name, c_name, error_condition) \ - STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { \ - mp_float_t x = mp_obj_get_float(x_obj); \ - if (error_condition) { \ - math_error(); \ - } \ - return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(x)); \ +#define MATH_FUN_2(py_name, c_name) \ + STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \ + return math_generic_2(x_obj, y_obj, MICROPY_FLOAT_C_FUN(c_name)); \ } \ - STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); + STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name); -#ifdef MP_NEED_LOG2 +#define MATH_FUN_2_FLT_INT(py_name, c_name) \ + STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \ + return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_int(y_obj))); \ + } \ + STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name); + +#if MP_NEED_LOG2 +#undef log2 +#undef log2f // 1.442695040888963407354163704 is 1/_M_LN2 -#define log2(x) (log(x) * 1.442695040888963407354163704) +mp_float_t MICROPY_FLOAT_C_FUN(log2)(mp_float_t x) { + return MICROPY_FLOAT_C_FUN(log)(x) * MICROPY_FLOAT_CONST(1.442695040888963407354163704); +} #endif // sqrt(x): returns the square root of x -MATH_FUN_1_ERRCOND(sqrt, sqrt, (x < (mp_float_t)0.0)) +MATH_FUN_1(sqrt, sqrt) // pow(x, y): returns x to the power of y MATH_FUN_2(pow, pow) // exp(x) @@ -81,9 +104,9 @@ MATH_FUN_1(exp, exp) // expm1(x) MATH_FUN_1(expm1, expm1) // log2(x) -MATH_FUN_1_ERRCOND(log2, log2, (x <= (mp_float_t)0.0)) +MATH_FUN_1(log2, log2) // log10(x) -MATH_FUN_1_ERRCOND(log10, log10, (x <= (mp_float_t)0.0)) +MATH_FUN_1(log10, log10) // cosh(x) MATH_FUN_1(cosh, cosh) // sinh(x) @@ -114,9 +137,15 @@ MATH_FUN_2(atan2, atan2) // ceil(x) MATH_FUN_1_TO_INT(ceil, ceil) // copysign(x, y) -MATH_FUN_2(copysign, copysign) +STATIC mp_float_t MICROPY_FLOAT_C_FUN(copysign_func)(mp_float_t x, mp_float_t y) { + return MICROPY_FLOAT_C_FUN(copysign)(x, y); +} +MATH_FUN_2(copysign, copysign_func) // fabs(x) -MATH_FUN_1(fabs, fabs) +STATIC mp_float_t MICROPY_FLOAT_C_FUN(fabs_func)(mp_float_t x) { + return MICROPY_FLOAT_C_FUN(fabs)(x); +} +MATH_FUN_1(fabs, fabs_func) // floor(x) MATH_FUN_1_TO_INT(floor, floor) //TODO: delegate to x.__floor__() if x is not a float // fmod(x, y) @@ -130,7 +159,7 @@ MATH_FUN_1_TO_BOOL(isnan, isnan) // trunc(x) MATH_FUN_1_TO_INT(trunc, trunc) // ldexp(x, exp) -MATH_FUN_2(ldexp, ldexp) +MATH_FUN_2_FLT_INT(ldexp, ldexp) #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS // erf(x): return the error function of x MATH_FUN_1(erf, erf) diff --git a/py/mpconfig.h b/py/mpconfig.h index cec9fb748..252ab7f37 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -775,16 +775,24 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_TIMEOUTERROR (0) #endif -// Whether to support complete set of special methods -// for user classes, or only the most used ones. "Reverse" -// methods are controlled by MICROPY_PY_REVERSE_SPECIAL_METHODS -// below. +// Whether to support complete set of special methods for user +// classes, or only the most used ones. "Inplace" methods are +// controlled by MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS below. +// "Reverse" methods are controlled by +// MICROPY_PY_REVERSE_SPECIAL_METHODS below. #ifndef MICROPY_PY_ALL_SPECIAL_METHODS #define MICROPY_PY_ALL_SPECIAL_METHODS (0) #endif -// Whether to support reverse arithmetic operarions methods -// (__radd__, etc.) +// Whether to support all inplace arithmetic operarion methods +// (__imul__, etc.) +#ifndef MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS +#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (0) +#endif + +// Whether to support reverse arithmetic operarion methods +// (__radd__, etc.). Additionally gated by +// MICROPY_PY_ALL_SPECIAL_METHODS. #ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS #define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) #endif @@ -1111,6 +1119,8 @@ typedef double mp_float_t; #ifndef MICROPY_PY_USSL #define MICROPY_PY_USSL (0) +// Whether to add finaliser code to ussl objects +#define MICROPY_PY_USSL_FINALISER (0) #endif #ifndef MICROPY_PY_WEBSOCKET diff --git a/py/mpstate.h b/py/mpstate.h index 1ffb5213c..23133cb7e 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -168,7 +168,7 @@ typedef struct _mp_state_vm_t { // root pointers for extmod #ifdef MICROPY_PY_OS_DUPTERM - mp_obj_t term_obj; + mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]; mp_obj_t dupterm_arr_obj; #endif diff --git a/py/nativeglue.c b/py/nativeglue.c index 61b624ec7..e63c2fcda 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -29,6 +29,7 @@ #include <assert.h> #include "py/runtime.h" +#include "py/smallint.h" #include "py/emitglue.h" #include "py/bc.h" @@ -170,6 +171,8 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_obj_new_cell, mp_make_closure_from_raw_code, mp_setup_code_state, + mp_small_int_floor_divide, + mp_small_int_modulo, }; /* diff --git a/py/objarray.c b/py/objarray.c index b8dca32f7..a1a979b56 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -286,7 +286,7 @@ STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs // Otherwise, can only look for a scalar numeric value in an array if (MP_OBJ_IS_INT(rhs_in) || mp_obj_is_float(rhs_in)) { - mp_raise_NotImplementedError(""); + mp_raise_NotImplementedError(NULL); } return mp_const_false; diff --git a/py/objlist.c b/py/objlist.c index c6e85f2c8..0cbf68c2f 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -158,7 +158,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { - mp_raise_NotImplementedError(""); + mp_raise_NotImplementedError(NULL); } mp_int_t len_adj = slice.start - slice.stop; @@ -198,7 +198,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_get_array(value, &value_len, &value_items); mp_bound_slice_t slice_out; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) { - mp_raise_NotImplementedError(""); + mp_raise_NotImplementedError(NULL); } mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start); //printf("Len adj: %d\n", len_adj); diff --git a/py/objtype.c b/py/objtype.c index d57cec703..2fefc65ad 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -335,7 +335,9 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size return MP_OBJ_FROM_PTR(o); } -const uint16_t mp_unary_op_method_name[] = { +// Qstrs for special methods are guaranteed to have a small value, so we use byte +// type to represent them. +const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = { [MP_UNARY_OP_BOOL] = MP_QSTR___bool__, [MP_UNARY_OP_LEN] = MP_QSTR___len__, [MP_UNARY_OP_HASH] = MP_QSTR___hash__, @@ -343,11 +345,11 @@ const uint16_t mp_unary_op_method_name[] = { [MP_UNARY_OP_POSITIVE] = MP_QSTR___pos__, [MP_UNARY_OP_NEGATIVE] = MP_QSTR___neg__, [MP_UNARY_OP_INVERT] = MP_QSTR___invert__, + [MP_UNARY_OP_ABS] = MP_QSTR___abs__, #endif #if MICROPY_PY_SYS_GETSIZEOF - [MP_UNARY_OP_SIZEOF] = MP_QSTR_getsizeof, + [MP_UNARY_OP_SIZEOF] = MP_QSTR___sizeof__, #endif - [MP_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this, used to make sure array has full size }; STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { @@ -409,59 +411,69 @@ STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -const uint16_t mp_binary_op_method_name[] = { - /* - MP_BINARY_OP_OR, - MP_BINARY_OP_XOR, - MP_BINARY_OP_AND, - MP_BINARY_OP_LSHIFT, - MP_BINARY_OP_RSHIFT, - */ +// Binary-op enum values not listed here will have the default value of 0 in the +// table, corresponding to MP_QSTR_NULL, and are therefore unsupported (a lookup will +// fail). They can be added at the expense of code size for the qstr. +// Qstrs for special methods are guaranteed to have a small value, so we use byte +// type to represent them. +const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = { + [MP_BINARY_OP_LESS] = MP_QSTR___lt__, + [MP_BINARY_OP_MORE] = MP_QSTR___gt__, + [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__, + [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__, + [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__, + // MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result + [MP_BINARY_OP_IN] = MP_QSTR___contains__, + + // All inplace methods are optional, and normal methods will be used + // as a fallback. + [MP_BINARY_OP_INPLACE_ADD] = MP_QSTR___iadd__, + [MP_BINARY_OP_INPLACE_SUBTRACT] = MP_QSTR___isub__, + #if MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS + [MP_BINARY_OP_INPLACE_MULTIPLY] = MP_QSTR___imul__, + [MP_BINARY_OP_INPLACE_FLOOR_DIVIDE] = MP_QSTR___ifloordiv__, + [MP_BINARY_OP_INPLACE_TRUE_DIVIDE] = MP_QSTR___itruediv__, + [MP_BINARY_OP_INPLACE_MODULO] = MP_QSTR___imod__, + [MP_BINARY_OP_INPLACE_POWER] = MP_QSTR___ipow__, + [MP_BINARY_OP_INPLACE_OR] = MP_QSTR___ior__, + [MP_BINARY_OP_INPLACE_XOR] = MP_QSTR___ixor__, + [MP_BINARY_OP_INPLACE_AND] = MP_QSTR___iand__, + [MP_BINARY_OP_INPLACE_LSHIFT] = MP_QSTR___ilshift__, + [MP_BINARY_OP_INPLACE_RSHIFT] = MP_QSTR___irshift__, + #endif + [MP_BINARY_OP_ADD] = MP_QSTR___add__, [MP_BINARY_OP_SUBTRACT] = MP_QSTR___sub__, #if MICROPY_PY_ALL_SPECIAL_METHODS [MP_BINARY_OP_MULTIPLY] = MP_QSTR___mul__, [MP_BINARY_OP_FLOOR_DIVIDE] = MP_QSTR___floordiv__, [MP_BINARY_OP_TRUE_DIVIDE] = MP_QSTR___truediv__, + [MP_BINARY_OP_MODULO] = MP_QSTR___mod__, + [MP_BINARY_OP_DIVMOD] = MP_QSTR___divmod__, + [MP_BINARY_OP_POWER] = MP_QSTR___pow__, + [MP_BINARY_OP_OR] = MP_QSTR___or__, + [MP_BINARY_OP_XOR] = MP_QSTR___xor__, + [MP_BINARY_OP_AND] = MP_QSTR___and__, + [MP_BINARY_OP_LSHIFT] = MP_QSTR___lshift__, + [MP_BINARY_OP_RSHIFT] = MP_QSTR___rshift__, #endif - /* - MP_BINARY_OP_MODULO, - MP_BINARY_OP_POWER, - MP_BINARY_OP_DIVMOD, - MP_BINARY_OP_INPLACE_OR, - MP_BINARY_OP_INPLACE_XOR, - MP_BINARY_OP_INPLACE_AND, - MP_BINARY_OP_INPLACE_LSHIFT, - MP_BINARY_OP_INPLACE_RSHIFT,*/ - #if MICROPY_PY_ALL_SPECIAL_METHODS - [MP_BINARY_OP_INPLACE_ADD] = MP_QSTR___iadd__, - [MP_BINARY_OP_INPLACE_SUBTRACT] = MP_QSTR___isub__, - #endif - /*MP_BINARY_OP_INPLACE_MULTIPLY, - MP_BINARY_OP_INPLACE_FLOOR_DIVIDE, - MP_BINARY_OP_INPLACE_TRUE_DIVIDE, - MP_BINARY_OP_INPLACE_MODULO, - MP_BINARY_OP_INPLACE_POWER,*/ #if MICROPY_PY_REVERSE_SPECIAL_METHODS [MP_BINARY_OP_REVERSE_ADD] = MP_QSTR___radd__, [MP_BINARY_OP_REVERSE_SUBTRACT] = MP_QSTR___rsub__, + #if MICROPY_PY_ALL_SPECIAL_METHODS [MP_BINARY_OP_REVERSE_MULTIPLY] = MP_QSTR___rmul__, + [MP_BINARY_OP_REVERSE_FLOOR_DIVIDE] = MP_QSTR___rfloordiv__, + [MP_BINARY_OP_REVERSE_TRUE_DIVIDE] = MP_QSTR___rtruediv__, + [MP_BINARY_OP_REVERSE_MODULO] = MP_QSTR___rmod__, + [MP_BINARY_OP_REVERSE_POWER] = MP_QSTR___rpow__, + [MP_BINARY_OP_REVERSE_OR] = MP_QSTR___ror__, + [MP_BINARY_OP_REVERSE_XOR] = MP_QSTR___rxor__, + [MP_BINARY_OP_REVERSE_AND] = MP_QSTR___rand__, + [MP_BINARY_OP_REVERSE_LSHIFT] = MP_QSTR___rlshift__, + [MP_BINARY_OP_REVERSE_RSHIFT] = MP_QSTR___rrshift__, + #endif #endif - - [MP_BINARY_OP_LESS] = MP_QSTR___lt__, - [MP_BINARY_OP_MORE] = MP_QSTR___gt__, - [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__, - [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__, - [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__, - /* - MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result - */ - [MP_BINARY_OP_IN] = MP_QSTR___contains__, - /* - MP_BINARY_OP_IS, - */ - [MP_BINARY_OP_LAST] = 0, // used to make sure array has full size, TODO: FIXME }; STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { diff --git a/py/persistentcode.c b/py/persistentcode.c index 42efcbfbb..477ba7501 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -39,7 +39,7 @@ #include "py/smallint.h" // The current version of .mpy files -#define MPY_VERSION (2) +#define MPY_VERSION (3) // The feature flags byte encodes the compile-time config options that // affect the generate bytecode. diff --git a/py/runtime.c b/py/runtime.c index 4af17dd09..cbec82f17 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -108,6 +108,13 @@ void mp_init(void) { MP_STATE_VM(mp_module_builtins_override_dict) = NULL; #endif + #ifdef MICROPY_PY_OS_DUPTERM + for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) { + MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL; + } + MP_STATE_VM(dupterm_arr_obj) = MP_OBJ_NULL; + #endif + #ifdef MICROPY_FSUSERMOUNT // zero out the pointers to the user-mounted devices memset(MP_STATE_VM(fs_user_mount) + MICROPY_FATFS_NUM_PERSISTENT, 0, diff --git a/py/runtime.h b/py/runtime.h index 79f5cbc92..a8b6312ff 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -57,8 +57,8 @@ typedef struct _mp_arg_t { } mp_arg_t; // Tables mapping operator enums to qstrs, defined in objtype.c -extern const uint16_t mp_unary_op_method_name[]; -extern const uint16_t mp_binary_op_method_name[]; +extern const byte mp_unary_op_method_name[]; +extern const byte mp_binary_op_method_name[]; void mp_init(void); void mp_deinit(void); diff --git a/py/runtime0.h b/py/runtime0.h index 8e95b68cf..4709430fb 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -53,41 +53,38 @@ typedef enum { MP_UNARY_OP_NOT, // Following ops cannot appear in the bytecode - MP_UNARY_OP_NON_BYTECODE, + MP_UNARY_OP_NUM_BYTECODE, - MP_UNARY_OP_BOOL = MP_UNARY_OP_NON_BYTECODE, // __bool__ + MP_UNARY_OP_BOOL = MP_UNARY_OP_NUM_BYTECODE, // __bool__ MP_UNARY_OP_LEN, // __len__ MP_UNARY_OP_HASH, // __hash__; must return a small int MP_UNARY_OP_ABS, // __abs__ MP_UNARY_OP_SIZEOF, // for sys.getsizeof() + + MP_UNARY_OP_NUM_RUNTIME, } mp_unary_op_t; -// Note: the first 35 of these are used in bytecode and changing +// Note: the first 9+12+12 of these are used in bytecode and changing // them requires changing the bytecode version. typedef enum { - // Relational operations, should return a bool + // 9 relational operations, should return a bool MP_BINARY_OP_LESS, MP_BINARY_OP_MORE, MP_BINARY_OP_EQUAL, MP_BINARY_OP_LESS_EQUAL, MP_BINARY_OP_MORE_EQUAL, MP_BINARY_OP_NOT_EQUAL, - MP_BINARY_OP_IN, MP_BINARY_OP_IS, MP_BINARY_OP_EXCEPTION_MATCH, - // these are not supported by the runtime and must be synthesised by the emitter - MP_BINARY_OP_NOT_IN, - MP_BINARY_OP_IS_NOT, - // Arithmetic operations + // 12 inplace arithmetic operations MP_BINARY_OP_INPLACE_OR, MP_BINARY_OP_INPLACE_XOR, MP_BINARY_OP_INPLACE_AND, MP_BINARY_OP_INPLACE_LSHIFT, MP_BINARY_OP_INPLACE_RSHIFT, MP_BINARY_OP_INPLACE_ADD, - MP_BINARY_OP_INPLACE_SUBTRACT, MP_BINARY_OP_INPLACE_MULTIPLY, MP_BINARY_OP_INPLACE_FLOOR_DIVIDE, @@ -95,13 +92,13 @@ typedef enum { MP_BINARY_OP_INPLACE_MODULO, MP_BINARY_OP_INPLACE_POWER, + // 12 normal arithmetic operations MP_BINARY_OP_OR, MP_BINARY_OP_XOR, MP_BINARY_OP_AND, MP_BINARY_OP_LSHIFT, MP_BINARY_OP_RSHIFT, MP_BINARY_OP_ADD, - MP_BINARY_OP_SUBTRACT, MP_BINARY_OP_MULTIPLY, MP_BINARY_OP_FLOOR_DIVIDE, @@ -111,16 +108,16 @@ typedef enum { // Operations below this line don't appear in bytecode, they // just identify special methods. + MP_BINARY_OP_NUM_BYTECODE, // MP_BINARY_OP_REVERSE_* must follow immediately after MP_BINARY_OP_* #if MICROPY_PY_REVERSE_SPECIAL_METHODS - MP_BINARY_OP_REVERSE_OR, + MP_BINARY_OP_REVERSE_OR = MP_BINARY_OP_NUM_BYTECODE, MP_BINARY_OP_REVERSE_XOR, MP_BINARY_OP_REVERSE_AND, MP_BINARY_OP_REVERSE_LSHIFT, MP_BINARY_OP_REVERSE_RSHIFT, MP_BINARY_OP_REVERSE_ADD, - MP_BINARY_OP_REVERSE_SUBTRACT, MP_BINARY_OP_REVERSE_MULTIPLY, MP_BINARY_OP_REVERSE_FLOOR_DIVIDE, @@ -129,9 +126,18 @@ typedef enum { MP_BINARY_OP_REVERSE_POWER, #endif - MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime + // This is not emitted by the compiler but is supported by the runtime + MP_BINARY_OP_DIVMOD + #if !MICROPY_PY_REVERSE_SPECIAL_METHODS + = MP_BINARY_OP_NUM_BYTECODE + #endif + , + + MP_BINARY_OP_NUM_RUNTIME, - MP_BINARY_OP_LAST, + // These 2 are not supported by the runtime and must be synthesised by the emitter + MP_BINARY_OP_NOT_IN, + MP_BINARY_OP_IS_NOT, } mp_binary_op_t; typedef enum { @@ -181,6 +187,8 @@ typedef enum { MP_F_NEW_CELL, MP_F_MAKE_CLOSURE_FROM_RAW_CODE, MP_F_SETUP_CODE_STATE, + MP_F_SMALL_INT_FLOOR_DIVIDE, + MP_F_SMALL_INT_MODULO, MP_F_NUMBER_OF, } mp_fun_kind_t; diff --git a/py/showbc.c b/py/showbc.c index 728d8d983..3deb18cd3 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -539,9 +539,9 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("LOAD_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI); } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) { printf("STORE_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI); - } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NON_BYTECODE) { + } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE) { printf("UNARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI); - } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) { + } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE) { mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI; printf("BINARY_OP " UINT_FMT " %s", op, qstr_str(mp_binary_op_method_name[op])); } else { diff --git a/py/vmentrytable.h b/py/vmentrytable.h index e634e2b41..615f4e2ce 100644 --- a/py/vmentrytable.h +++ b/py/vmentrytable.h @@ -109,8 +109,8 @@ static const void *const entry_table[256] = { [MP_BC_LOAD_CONST_SMALL_INT_MULTI ... MP_BC_LOAD_CONST_SMALL_INT_MULTI + 63] = &&entry_MP_BC_LOAD_CONST_SMALL_INT_MULTI, [MP_BC_LOAD_FAST_MULTI ... MP_BC_LOAD_FAST_MULTI + 15] = &&entry_MP_BC_LOAD_FAST_MULTI, [MP_BC_STORE_FAST_MULTI ... MP_BC_STORE_FAST_MULTI + 15] = &&entry_MP_BC_STORE_FAST_MULTI, - [MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NON_BYTECODE - 1] = &&entry_MP_BC_UNARY_OP_MULTI, - [MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + 35] = &&entry_MP_BC_BINARY_OP_MULTI, + [MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE - 1] = &&entry_MP_BC_UNARY_OP_MULTI, + [MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE - 1] = &&entry_MP_BC_BINARY_OP_MULTI, }; #if __clang__ |
