summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--bare-arm/Makefile4
-rw-r--r--py/asmthumb.c2
-rw-r--r--py/asmx64.c2
-rw-r--r--py/binary.c50
-rw-r--r--py/binary.h1
-rw-r--r--py/builtin.c4
-rw-r--r--py/builtintables.c12
-rw-r--r--py/compile.c6
-rw-r--r--py/emitbc.c2
-rw-r--r--py/emitcommon.c2
-rw-r--r--py/emitcpy.c2
-rw-r--r--py/emitglue.c2
-rw-r--r--py/emitinlinethumb.c6
-rw-r--r--py/emitnative.c9
-rw-r--r--py/emitpass1.c2
-rw-r--r--py/gc.c8
-rw-r--r--py/lexer.c8
-rw-r--r--py/lexerstr.c2
-rw-r--r--py/lexerunix.c2
-rw-r--r--py/malloc.c2
-rw-r--r--py/map.c2
-rw-r--r--py/misc.h2
-rw-r--r--py/mkrules.mk4
-rw-r--r--py/modarray.c6
-rw-r--r--py/modcmath.c6
-rw-r--r--py/modcollections.c6
-rw-r--r--py/modgc.c22
-rw-r--r--py/modio.c6
-rw-r--r--py/modmath.c6
-rw-r--r--py/modmicropython.c6
-rw-r--r--py/modstruct.c6
-rw-r--r--py/modsys.c6
-rw-r--r--py/mpconfig.h10
-rw-r--r--py/mpz.c2
-rw-r--r--py/nlr.h3
-rw-r--r--py/nlrthumb.S12
-rw-r--r--py/obj.c2
-rw-r--r--py/objcomplex.c2
-rw-r--r--py/objenumerate.c4
-rw-r--r--py/objfloat.c5
-rw-r--r--py/objfun.c6
-rw-r--r--py/objint_mpz.c2
-rw-r--r--py/parse.c2
-rw-r--r--py/parsehelper.c2
-rw-r--r--py/parsenum.c8
-rw-r--r--py/parsenumbase.c2
-rw-r--r--py/pfenv.c2
-rw-r--r--py/py.mk1
-rw-r--r--py/qstr.c2
-rw-r--r--py/qstrdefs.h2
-rw-r--r--py/repl.c2
-rw-r--r--py/runtime.c2
-rw-r--r--py/scope.c2
-rw-r--r--py/smallint.c2
-rw-r--r--py/stackctrl.c63
-rw-r--r--py/stackctrl.h41
-rw-r--r--py/unicode.c2
-rw-r--r--py/vstr.c2
-rw-r--r--stmhal/Makefile4
-rw-r--r--stmhal/adc.c10
-rw-r--r--stmhal/dac.c2
-rw-r--r--stmhal/extint.c2
-rw-r--r--stmhal/i2c.c10
-rw-r--r--stmhal/led.c15
-rw-r--r--stmhal/main.c8
-rw-r--r--stmhal/modos.c4
-rw-r--r--stmhal/modpyb.c4
-rw-r--r--stmhal/modstm.c4
-rw-r--r--stmhal/modtime.c4
-rw-r--r--stmhal/pin.c8
-rw-r--r--stmhal/spi.c10
-rw-r--r--stmhal/timer.c4
-rw-r--r--stmhal/uart.c6
-rw-r--r--teensy/Makefile2
-rw-r--r--tests/basics/struct1.py4
-rw-r--r--tests/bench/arrayop-1-list_inplace.py12
-rw-r--r--tests/bench/arrayop-2-list_map.py12
-rw-r--r--tests/bench/arrayop-3-bytearray_inplace.py12
-rw-r--r--tests/bench/arrayop-4-bytearray_map.py12
-rw-r--r--tests/bench/bytebuf-1-inplace.py11
-rw-r--r--tests/bench/bytebuf-2-join_map_bytes.py12
-rw-r--r--tests/bench/bytebuf-3-bytarray_map.py10
-rw-r--r--tests/bench/from_iter-1-list_bound.py8
-rw-r--r--tests/bench/from_iter-2-list_unbound.py8
-rw-r--r--tests/bench/from_iter-3-tuple_bound.py8
-rw-r--r--tests/bench/from_iter-4-tuple_unbound.py8
-rw-r--r--tests/bench/from_iter-5-bytes_bound.py8
-rw-r--r--tests/bench/from_iter-6-bytes_unbound.py8
-rw-r--r--tests/bench/from_iter-7-bytearray_bound.py8
-rw-r--r--tests/bench/from_iter-8-bytearray_unbound.py8
-rw-r--r--tests/bench/funcall-1-inline.py9
-rw-r--r--tests/bench/funcall-2-funcall.py12
-rw-r--r--tests/bench/funcall-3-funcall-local.py16
-rw-r--r--tests/float/math-fun-bool.py7
-rw-r--r--tests/float/math-fun.py7
-rw-r--r--tests/misc/recursion.py7
-rw-r--r--unix/Makefile32
-rw-r--r--unix/gccollect.c10
-rw-r--r--unix/main.c20
-rw-r--r--unix/modffi.c4
-rw-r--r--unix/modos.c4
-rw-r--r--unix/modsocket.c31
-rw-r--r--unix/modtime.c4
-rw-r--r--unix/mpconfigport.h2
-rw-r--r--windows/Makefile2
-rw-r--r--windows/bss.c74
-rw-r--r--windows/init.c3
-rw-r--r--windows/mpconfigport.h19
-rw-r--r--windows/msvc/common.props3
-rw-r--r--windows/msvc/sources.props2
111 files changed, 701 insertions, 206 deletions
diff --git a/.travis.yml b/.travis.yml
index e6c12b9677..489cceaa27 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,4 +20,4 @@ script:
- (cd tests && MICROPY_CPYTHON3=python3.3 ./run-tests)
after_failure:
- - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff $testbase.exp $testbase.out; done)
+ - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done)
diff --git a/bare-arm/Makefile b/bare-arm/Makefile
index 745945deb6..ed8c00482b 100644
--- a/bare-arm/Makefile
+++ b/bare-arm/Makefile
@@ -13,7 +13,7 @@ INC += -I$(PY_SRC)
INC += -I$(BUILD)
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
-CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) $(COPT)
+CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
#Debugging/Optimization
ifeq ($(DEBUG), 1)
@@ -22,7 +22,7 @@ else
CFLAGS += -Os -DNDEBUG
endif
-LDFLAGS = --nostdlib -T stm32f405.ld
+LDFLAGS = -nostdlib -T stm32f405.ld
LIBS =
SRC_C = \
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 891947567b..03752ed938 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -28,8 +28,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "asmthumb.h"
// wrapper around everything in this file
diff --git a/py/asmx64.c b/py/asmx64.c
index 6c22ea25de..4695bdc731 100644
--- a/py/asmx64.c
+++ b/py/asmx64.c
@@ -29,8 +29,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
// wrapper around everything in this file
#if MICROPY_EMIT_X64
diff --git a/py/binary.c b/py/binary.c
index 833d9c85ad..d755bc86e0 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -29,8 +29,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "binary.h"
@@ -125,24 +125,9 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
return MP_OBJ_NEW_SMALL_INT(val);
}
-#define is_signed(typecode) (typecode > 'Z')
-mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
- byte *p = *ptr;
- uint align;
-
- int size = mp_binary_get_size(struct_type, val_type, &align);
- if (struct_type == '@') {
- // Make pointer aligned
- p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
- #if MP_ENDIANNESS_LITTLE
- struct_type = '<';
- #else
- struct_type = '>';
- #endif
- }
-
+machine_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p) {
int delta;
- if (struct_type == '<') {
+ if (!big_endian) {
delta = -1;
p += size - 1;
} else {
@@ -150,7 +135,7 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
}
machine_int_t val = 0;
- if (is_signed(val_type) && *p & 0x80) {
+ if (is_signed && *p & 0x80) {
val = -1;
}
for (uint i = 0; i < size; i++) {
@@ -159,7 +144,28 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
p += delta;
}
- *ptr += size;
+ return val;
+}
+
+#define is_signed(typecode) (typecode > 'Z')
+mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
+ byte *p = *ptr;
+ uint align;
+
+ int size = mp_binary_get_size(struct_type, val_type, &align);
+ if (struct_type == '@') {
+ // Make pointer aligned
+ p = (byte*)(((machine_uint_t)p + align - 1) & ~((machine_uint_t)align - 1));
+ #if MP_ENDIANNESS_LITTLE
+ struct_type = '<';
+ #else
+ struct_type = '>';
+ #endif
+ }
+ *ptr = p + size;
+
+ machine_int_t val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
+
if (val_type == 'O') {
return (mp_obj_t)val;
} else if (val_type == 'S') {
@@ -178,13 +184,14 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
int size = mp_binary_get_size(struct_type, val_type, &align);
if (struct_type == '@') {
// Make pointer aligned
- p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
+ p = (byte*)(((machine_uint_t)p + align - 1) & ~((machine_uint_t)align - 1));
#if MP_ENDIANNESS_LITTLE
struct_type = '<';
#else
struct_type = '>';
#endif
}
+ *ptr = p + size;
#if MP_ENDIANNESS_BIG
#error Not implemented
@@ -215,7 +222,6 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
in += in_delta;
}
- *ptr += size;
}
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) {
diff --git a/py/binary.h b/py/binary.h
index f15a2fd7fb..63ea5d741e 100644
--- a/py/binary.h
+++ b/py/binary.h
@@ -34,3 +34,4 @@ void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in)
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val);
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);
+machine_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p);
diff --git a/py/builtin.c b/py/builtin.c
index 834108f1b5..d4b77d37a8 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -113,11 +113,13 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
} else {
return o_in;
}
+#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) {
mp_float_t real, imag;
mp_obj_complex_get(o_in, &real, &imag);
return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag));
#endif
+#endif
} else {
assert(0);
return mp_const_none;
@@ -154,7 +156,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);
STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) {
mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in };
- return mp_obj_str_format(ARRAY_SIZE(args), args);
+ return mp_obj_str_format(MP_ARRAY_SIZE(args), args);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin);
diff --git a/py/builtintables.c b/py/builtintables.c
index 857a581de4..8b4df93177 100644
--- a/py/builtintables.c
+++ b/py/builtintables.c
@@ -26,8 +26,8 @@
#include <stdlib.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -44,7 +44,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_bool), (mp_obj_t)&mp_type_bool },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytes), (mp_obj_t)&mp_type_bytes },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytearray), (mp_obj_t)&mp_type_bytearray },
-#if MICROPY_PY_BUILTINS_FLOAT
+#if MICROPY_PY_BUILTINS_COMPLEX
{ MP_OBJ_NEW_QSTR(MP_QSTR_complex), (mp_obj_t)&mp_type_complex },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&mp_type_dict },
@@ -150,8 +150,8 @@ const mp_obj_dict_t mp_builtin_object_dict_obj = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_builtin_object_table),
- .alloc = ARRAY_SIZE(mp_builtin_object_table),
+ .used = MP_ARRAY_SIZE(mp_builtin_object_table),
+ .alloc = MP_ARRAY_SIZE(mp_builtin_object_table),
.table = (mp_map_elem_t*)mp_builtin_object_table,
},
};
@@ -195,8 +195,8 @@ const mp_obj_dict_t mp_builtin_module_dict_obj = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_builtin_module_table),
- .alloc = ARRAY_SIZE(mp_builtin_module_table),
+ .used = MP_ARRAY_SIZE(mp_builtin_module_table),
+ .alloc = MP_ARRAY_SIZE(mp_builtin_module_table),
.table = (mp_map_elem_t*)mp_builtin_module_table,
},
};
diff --git a/py/compile.c b/py/compile.c
index 946c8924b2..d49edd6ef3 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -31,8 +31,8 @@
#include <assert.h>
#include <math.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -111,8 +111,8 @@ STATIC const mp_map_elem_t mp_constants_table[] = {
STATIC const mp_map_t mp_constants_map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_constants_table),
- .alloc = ARRAY_SIZE(mp_constants_table),
+ .used = MP_ARRAY_SIZE(mp_constants_table),
+ .alloc = MP_ARRAY_SIZE(mp_constants_table),
.table = (mp_map_elem_t*)mp_constants_table,
};
diff --git a/py/emitbc.c b/py/emitbc.c
index 841dd4aabb..3eb0d575b9 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/py/emitcommon.c b/py/emitcommon.c
index ea65183623..4649793134 100644
--- a/py/emitcommon.c
+++ b/py/emitcommon.c
@@ -28,8 +28,8 @@
#include <stdint.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/py/emitcpy.c b/py/emitcpy.c
index a8a6265b8c..fbca3805b3 100644
--- a/py/emitcpy.c
+++ b/py/emitcpy.c
@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/py/emitglue.c b/py/emitglue.c
index f9b9460837..17dc8f867c 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 79ed1c4a02..435e1b64d9 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -30,8 +30,8 @@
#include <stdarg.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -167,7 +167,7 @@ STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t
if (MP_PARSE_NODE_IS_ID(pn)) {
qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
const char *reg_str = qstr_str(reg_qstr);
- for (uint i = 0; i < ARRAY_SIZE(reg_name_table); i++) {
+ for (uint i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {
const reg_name_t *r = &reg_name_table[i];
if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) {
if (r->reg > max_reg) {
@@ -286,7 +286,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
asm_thumb_b_n(emit->as, label_num);
} else if (op_str[0] == 'b' && op_len == 3) {
uint cc = -1;
- for (uint i = 0; i < ARRAY_SIZE(cc_name_table); i++) {
+ for (uint i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {
if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) {
cc = cc_name_table[i].cc;
}
diff --git a/py/emitnative.c b/py/emitnative.c
index 4dac5ffb09..f291efe481 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -48,8 +48,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
@@ -917,8 +917,11 @@ STATIC void emit_native_delete_global(emit_t *emit, qstr qstr) {
}
STATIC void emit_native_delete_attr(emit_t *emit, qstr qstr) {
- // not supported
- assert(0);
+ vtype_kind_t vtype_base;
+ emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
+ assert(vtype_base == VTYPE_PYOBJ);
+ emit_call_with_2_imm_args(emit, MP_F_STORE_ATTR, mp_store_attr, qstr, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg2 = attribute name, arg3 = value (null for delete)
+ emit_post(emit);
}
STATIC void emit_native_delete_subscr(emit_t *emit) {
diff --git a/py/emitpass1.c b/py/emitpass1.c
index 2e76420a21..bea1af4dbf 100644
--- a/py/emitpass1.c
+++ b/py/emitpass1.c
@@ -28,8 +28,8 @@
#include <stdint.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/py/gc.c b/py/gc.c
index 30bae5054a..65bfea0b35 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -33,7 +33,6 @@
#include "misc.h"
#include "gc.h"
-#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -113,7 +112,7 @@ STATIC machine_uint_t gc_lock_depth;
void gc_init(void *start, void *end) {
// align end pointer on block boundary
end = (void*)((machine_uint_t)end & (~(BYTES_PER_BLOCK - 1)));
- DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, end - start);
+ DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte*)end - (byte*)start);
// calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes):
// T = A + F + P
@@ -268,6 +267,7 @@ STATIC void gc_sweep(void) {
case AT_TAIL:
if (free_tail) {
+ DEBUG_printf("gc_sweep(%p)\n",PTR_FROM_BLOCK(block));
ATB_ANY_TO_FREE(block);
}
break;
@@ -401,6 +401,7 @@ found:
// get pointer to first block
void *ret_ptr = (void*)(gc_pool_start + start_block * WORDS_PER_BLOCK);
+ DEBUG_printf("gc_alloc(%p)\n", ret_ptr);
// zero out the additional bytes of the newly allocated blocks
// This is needed because the blocks may have previously held pointers
@@ -439,6 +440,7 @@ void gc_free(void *ptr_in) {
}
machine_uint_t ptr = (machine_uint_t)ptr_in;
+ DEBUG_printf("gc_free(%p)\n", ptr);
if (VERIFY_PTR(ptr)) {
machine_uint_t block = BLOCK_FROM_PTR(ptr);
@@ -590,7 +592,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
return NULL;
}
- DEBUG_printf("gc_realloc: allocating new block\n");
+ DEBUG_printf("gc_realloc(%p -> %p)\n", ptr_in, ptr_out);
memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK);
gc_free(ptr_in);
return ptr_out;
diff --git a/py/lexer.c b/py/lexer.c
index a65df54ba6..5d1113fb30 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -32,8 +32,8 @@
#include <stdio.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
@@ -694,10 +694,10 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
// need to check for this special token in many places in the compiler.
// TODO improve speed of these string comparisons
//for (int i = 0; tok_kw[i] != NULL; i++) {
- for (int i = 0; i < ARRAY_SIZE(tok_kw); i++) {
+ for (int i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
if (str_strn_equal(tok_kw[i], tok->str, tok->len)) {
- if (i == ARRAY_SIZE(tok_kw) - 1) {
- // tok_kw[ARRAY_SIZE(tok_kw) - 1] == "__debug__"
+ if (i == MP_ARRAY_SIZE(tok_kw) - 1) {
+ // tok_kw[MP_ARRAY_SIZE(tok_kw) - 1] == "__debug__"
tok->kind = (mp_optimise_value == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
} else {
tok->kind = MP_TOKEN_KW_FALSE + i;
diff --git a/py/lexerstr.c b/py/lexerstr.c
index 76e90671be..666dbfa37c 100644
--- a/py/lexerstr.c
+++ b/py/lexerstr.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
diff --git a/py/lexerunix.c b/py/lexerunix.c
index 89dc80b004..51bc915b22 100644
--- a/py/lexerunix.c
+++ b/py/lexerunix.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#if MICROPY_HELPER_LEXER_UNIX
diff --git a/py/malloc.c b/py/malloc.c
index b180ddf6b5..8e90849e93 100644
--- a/py/malloc.c
+++ b/py/malloc.c
@@ -28,8 +28,8 @@
#include <stdlib.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#if 0 // print debugging info
#define DEBUG_printf DEBUG_printf
diff --git a/py/map.c b/py/map.c
index 4020401622..dcc13c52cc 100644
--- a/py/map.c
+++ b/py/map.c
@@ -27,8 +27,8 @@
#include <stdlib.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime0.h"
diff --git a/py/misc.h b/py/misc.h
index 044fef6236..3f62e3198f 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -82,7 +82,7 @@ int m_get_peak_bytes_allocated(void);
/** array helpers ***********************************************/
// get the number of elements in a fixed-size array
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/** unichar / UTF-8 *********************************************/
diff --git a/py/mkrules.mk b/py/mkrules.mk
index 9592d6c590..6153618fae 100644
--- a/py/mkrules.mk
+++ b/py/mkrules.mk
@@ -73,9 +73,9 @@ all: $(PROG)
$(PROG): $(OBJ)
$(ECHO) "LINK $@"
- $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
+ $(Q)$(CC) $(COPT) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
ifndef DEBUG
- $(Q)$(STRIP) $(PROG)
+ $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)
endif
$(Q)$(SIZE) $(PROG)
diff --git a/py/modarray.c b/py/modarray.c
index a741a0ecb4..3ff567f1d9 100644
--- a/py/modarray.c
+++ b/py/modarray.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -40,8 +40,8 @@ STATIC const mp_obj_dict_t mp_module_array_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_array_globals_table),
- .alloc = ARRAY_SIZE(mp_module_array_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_array_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_array_globals_table),
.table = (mp_map_elem_t*)mp_module_array_globals_table,
},
};
diff --git a/py/modcmath.c b/py/modcmath.c
index 3bc3055dc8..ddd8abf71e 100644
--- a/py/modcmath.c
+++ b/py/modcmath.c
@@ -26,8 +26,8 @@
#include <math.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -142,8 +142,8 @@ STATIC const mp_obj_dict_t mp_module_cmath_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_cmath_globals_table),
- .alloc = ARRAY_SIZE(mp_module_cmath_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_cmath_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_cmath_globals_table),
.table = (mp_map_elem_t*)mp_module_cmath_globals_table,
},
};
diff --git a/py/modcollections.c b/py/modcollections.c
index 9e3da7e666..5cd0b317a1 100644
--- a/py/modcollections.c
+++ b/py/modcollections.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -42,8 +42,8 @@ STATIC const mp_obj_dict_t mp_module_collections_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_collections_globals_table),
- .alloc = ARRAY_SIZE(mp_module_collections_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_collections_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_collections_globals_table),
.table = (mp_map_elem_t*)mp_module_collections_globals_table,
},
};
diff --git a/py/modgc.c b/py/modgc.c
index c53eed235f..4ffdc2be68 100644
--- a/py/modgc.c
+++ b/py/modgc.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -61,11 +61,27 @@ STATIC mp_obj_t gc_enable(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable);
+STATIC mp_obj_t gc_mem_free(void) {
+ gc_info_t info;
+ gc_info(&info);
+ return MP_OBJ_NEW_SMALL_INT((machine_uint_t)info.free);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free);
+
+STATIC mp_obj_t gc_mem_alloc(void) {
+ gc_info_t info;
+ gc_info(&info);
+ return MP_OBJ_NEW_SMALL_INT((machine_uint_t)info.used);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_alloc_obj, gc_mem_alloc);
+
STATIC const mp_map_elem_t mp_module_gc_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_gc) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_collect), (mp_obj_t)&gc_collect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&gc_disable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&gc_enable_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mem_free), (mp_obj_t)&gc_mem_free_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mem_alloc), (mp_obj_t)&gc_mem_alloc_obj },
};
STATIC const mp_obj_dict_t mp_module_gc_globals = {
@@ -73,8 +89,8 @@ STATIC const mp_obj_dict_t mp_module_gc_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_gc_globals_table),
- .alloc = ARRAY_SIZE(mp_module_gc_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_gc_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_gc_globals_table),
.table = (mp_map_elem_t*)mp_module_gc_globals_table,
},
};
diff --git a/py/modio.c b/py/modio.c
index 08c6c59dd9..ef3b29b53f 100644
--- a/py/modio.c
+++ b/py/modio.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -57,8 +57,8 @@ STATIC const mp_obj_dict_t mp_module_io_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_io_globals_table),
- .alloc = ARRAY_SIZE(mp_module_io_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_io_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_io_globals_table),
.table = (mp_map_elem_t*)mp_module_io_globals_table,
},
};
diff --git a/py/modmath.c b/py/modmath.c
index 0fd583c2ff..0d0d13b4e2 100644
--- a/py/modmath.c
+++ b/py/modmath.c
@@ -26,8 +26,8 @@
#include <math.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -172,8 +172,8 @@ STATIC const mp_obj_dict_t mp_module_math_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_math_globals_table),
- .alloc = ARRAY_SIZE(mp_module_math_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_math_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_math_globals_table),
.table = (mp_map_elem_t*)mp_module_math_globals_table,
},
};
diff --git a/py/modmicropython.c b/py/modmicropython.c
index 40d749da2d..bbb315189b 100644
--- a/py/modmicropython.c
+++ b/py/modmicropython.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -65,8 +65,8 @@ STATIC const mp_obj_dict_t mp_module_micropython_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_micropython_globals_table),
- .alloc = ARRAY_SIZE(mp_module_micropython_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_micropython_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_micropython_globals_table),
.table = (mp_map_elem_t*)mp_module_micropython_globals_table,
},
};
diff --git a/py/modstruct.c b/py/modstruct.c
index a45181852c..2e40264e8d 100644
--- a/py/modstruct.c
+++ b/py/modstruct.c
@@ -27,8 +27,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -210,8 +210,8 @@ STATIC const mp_obj_dict_t mp_module_struct_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_struct_globals_table),
- .alloc = ARRAY_SIZE(mp_module_struct_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_struct_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_struct_globals_table),
.table = (mp_map_elem_t*)mp_module_struct_globals_table,
},
};
diff --git a/py/modsys.c b/py/modsys.c
index a99db1b7f8..1e7f7eff7f 100644
--- a/py/modsys.c
+++ b/py/modsys.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "builtin.h"
@@ -87,8 +87,8 @@ STATIC const mp_obj_dict_t mp_module_sys_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_sys_globals_table),
- .alloc = ARRAY_SIZE(mp_module_sys_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_sys_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_sys_globals_table),
.table = (mp_map_elem_t*)mp_module_sys_globals_table,
},
};
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 93e98c25b6..d7504c1402 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -157,6 +157,12 @@
#define MICROPY_ENABLE_GC_FINALISER (0)
#endif
+// Whether to check C stack usage. C stack used for calling Python functions,
+// etc. Not checking means segfault on overflow.
+#ifndef MICROPY_STACK_CHECK
+#define MICROPY_STACK_CHECK (1)
+#endif
+
// Whether to include REPL helper function
#ifndef MICROPY_HELPER_REPL
#define MICROPY_HELPER_REPL (0)
@@ -223,6 +229,10 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_FLOAT (0)
#endif
+#ifndef MICROPY_PY_BUILTINS_COMPLEX
+#define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT)
+#endif
+
// Enable features which improve CPython compatibility
// but may lead to more code size/memory usage.
// TODO: Originally intended as generic category to not
diff --git a/py/mpz.c b/py/mpz.c
index ab300b91df..3f1e859fc6 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -30,8 +30,8 @@
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "mpz.h"
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
diff --git a/py/nlr.h b/py/nlr.h
index 43a0c4f6a9..cb2b53b854 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -29,6 +29,7 @@
#include <limits.h>
#include <setjmp.h>
+#include <assert.h>
typedef struct _nlr_buf_t nlr_buf_t;
struct _nlr_buf_t {
@@ -44,7 +45,7 @@ struct _nlr_buf_t {
#else
void *regs[8];
#endif
-#elif defined(__thumb2__)
+#elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__)
void *regs[10];
#else
#define MICROPY_NLR_SETJMP (1)
diff --git a/py/nlrthumb.S b/py/nlrthumb.S
index b306c01753..dabf57cf85 100644
--- a/py/nlrthumb.S
+++ b/py/nlrthumb.S
@@ -24,19 +24,21 @@
* THE SOFTWARE.
*/
-#if defined(__thumb2__) && !MICROPY_NLR_SETJMP
-/* thumb callee save: bx, bp, sp, r12, r14, r14, r15 */
+#if !MICROPY_NLR_SETJMP && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
+/* arm callee save: bx, bp, sp, r12, r14, r14, r15 */
.syntax unified
/*.cpu cortex-m4*/
- .thumb
+ /*.thumb*/
.text
.align 2
/* uint nlr_push(r0=nlr_buf_t *nlr) */
.global nlr_push
+#if defined(__thumb2__)
.thumb
.thumb_func
+#endif
.type nlr_push, %function
nlr_push:
str lr, [r0, #8] @ store lr into nlr_buf
@@ -64,8 +66,10 @@ nlr_push:
@ void nlr_pop()
.global nlr_pop
+#if defined(__thumb2__)
.thumb
.thumb_func
+#endif
.type nlr_pop, %function
nlr_pop:
ldr r3, .L5 @ load addr of nlr_top
@@ -80,8 +84,10 @@ nlr_pop:
/* void nlr_jump(r0=uint val) */
.global nlr_jump
+#if defined(__thumb2__)
.thumb
.thumb_func
+#endif
.type nlr_jump, %function
nlr_jump:
ldr r3, .L2 @ load addr of nlr_top
diff --git a/py/obj.c b/py/obj.c
index 6d0966db24..a0f55d65db 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -274,6 +274,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
}
}
+#if MICROPY_PY_BUILTINS_COMPLEX
void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
if (arg == mp_const_false) {
*real = 0;
@@ -297,6 +298,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
}
}
#endif
+#endif
void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items) {
if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {
diff --git a/py/objcomplex.c b/py/objcomplex.c
index d58b53463c..20e7c97d37 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -36,7 +36,7 @@
#include "runtime0.h"
#include "runtime.h"
-#if MICROPY_PY_BUILTINS_FLOAT
+#if MICROPY_PY_BUILTINS_COMPLEX
#include <math.h>
diff --git a/py/objenumerate.c b/py/objenumerate.c
index 7d9ea9915a..37414464de 100644
--- a/py/objenumerate.c
+++ b/py/objenumerate.c
@@ -27,8 +27,8 @@
#include <stdlib.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
@@ -45,7 +45,7 @@ STATIC const mp_arg_t enumerate_make_new_args[] = {
{ MP_QSTR_iterable, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_start, MP_ARG_INT, {.u_int = 0} },
};
-#define ENUMERATE_MAKE_NEW_NUM_ARGS ARRAY_SIZE(enumerate_make_new_args)
+#define ENUMERATE_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(enumerate_make_new_args)
STATIC mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
#if MICROPY_CPYTHON_COMPAT
diff --git a/py/objfloat.c b/py/objfloat.c
index b608b1a3d7..e3fefad8db 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -102,9 +102,12 @@ STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_float_t *lhs = lhs_in;
+#if MICROPY_PY_BUILTINS_COMPLEX
if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in);
- } else {
+ } else
+#endif
+ {
return mp_obj_float_binary_op(op, lhs->value, rhs_in);
}
}
diff --git a/py/objfun.c b/py/objfun.c
index 29363129b2..f75e9142a2 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -39,6 +39,7 @@
#include "runtime0.h"
#include "runtime.h"
#include "bc.h"
+#include "stackctrl.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
@@ -204,6 +205,8 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, ui
// code_state should have ->ip filled in (pointing past code info block),
// as well as ->n_state.
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, uint n_args, uint 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.
mp_obj_fun_bc_t *self = self_in;
machine_uint_t n_state = code_state->n_state;
const byte *ip = code_state->ip;
@@ -353,8 +356,7 @@ continue2:;
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint 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.
+ STACK_CHECK();
DEBUG_printf("Input n_args: %d, n_kw: %d\n", n_args, n_kw);
DEBUG_printf("Input pos args: ");
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 516fb52746..cf7896f9e1 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -121,9 +121,11 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
#if MICROPY_PY_BUILTINS_FLOAT
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_float)) {
return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
+#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);
#endif
+#endif
} else {
// delegate to generic function to check for extra cases
return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
diff --git a/py/parse.c b/py/parse.c
index af09c335f2..492c1678b5 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -30,8 +30,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parsenumbase.h"
diff --git a/py/parsehelper.c b/py/parsehelper.c
index 3ead5a3031..105afe711e 100644
--- a/py/parsehelper.c
+++ b/py/parsehelper.c
@@ -29,8 +29,8 @@
#include <stdint.h>
#include <stdio.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
diff --git a/py/parsenum.c b/py/parsenum.c
index 1c1868ae0a..b9801ab6a1 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -27,14 +27,15 @@
#include <stdbool.h>
#include <stdlib.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "nlr.h"
#include "obj.h"
#include "parsenumbase.h"
#include "parsenum.h"
#include "smallint.h"
+#include "runtime.h"
#if MICROPY_PY_BUILTINS_FLOAT
#include <math.h>
@@ -252,10 +253,15 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
}
// return the object
+#if MICROPY_PY_BUILTINS_COMPLEX
if (imag) {
return mp_obj_new_complex(0, dec_val);
} else if (force_complex) {
return mp_obj_new_complex(dec_val, 0);
+#else
+ if (imag || force_complex) {
+ mp_not_implemented("complex values not supported");
+#endif
} else {
return mp_obj_new_float(dec_val);
}
diff --git a/py/parsenumbase.c b/py/parsenumbase.c
index ce140655bd..4fddac9c3d 100644
--- a/py/parsenumbase.c
+++ b/py/parsenumbase.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "parsenumbase.h"
// find real radix base, and strip preceding '0x', '0o' and '0b'
diff --git a/py/pfenv.c b/py/pfenv.c
index e631f8654a..ca1e3e919b 100644
--- a/py/pfenv.c
+++ b/py/pfenv.c
@@ -27,8 +27,8 @@
#include <stdint.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "mpz.h"
diff --git a/py/py.mk b/py/py.mk
index 2b74f252cf..374bb11d61 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -43,6 +43,7 @@ PY_O_BASENAME = \
parsenum.o \
emitglue.o \
runtime.o \
+ stackctrl.o \
argcheck.o \
map.o \
obj.o \
diff --git a/py/qstr.c b/py/qstr.c
index 7ccb34f1c3..10bc20ecba 100644
--- a/py/qstr.c
+++ b/py/qstr.c
@@ -27,8 +27,8 @@
#include <assert.h>
#include <string.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 856853fa55..4ff9ca87c8 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -377,6 +377,8 @@ Q(gc)
Q(collect)
Q(disable)
Q(enable)
+Q(mem_free)
+Q(mem_alloc)
#endif
#if MICROPY_PY_BUILTINS_PROPERTY
diff --git a/py/repl.c b/py/repl.c
index 457ce165b7..2c3dfbd4d9 100644
--- a/py/repl.c
+++ b/py/repl.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "repl.h"
#if MICROPY_HELPER_REPL
diff --git a/py/runtime.c b/py/runtime.c
index d57bb686d1..b539984c0b 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -426,6 +426,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
} else {
return res;
}
+#if MICROPY_PY_BUILTINS_COMPLEX
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {
mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
if (res == MP_OBJ_NULL) {
@@ -434,6 +435,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
return res;
}
#endif
+#endif
}
}
diff --git a/py/scope.c b/py/scope.c
index 839e8216c1..83c2b6e07c 100644
--- a/py/scope.c
+++ b/py/scope.c
@@ -29,8 +29,8 @@
#include <stdio.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "parse.h"
diff --git a/py/smallint.c b/py/smallint.c
index 5543f126c3..c57f364e36 100644
--- a/py/smallint.c
+++ b/py/smallint.c
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "smallint.h"
diff --git a/py/stackctrl.c b/py/stackctrl.c
new file mode 100644
index 0000000000..aef9bad9e9
--- /dev/null
+++ b/py/stackctrl.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Paul Sokolovsky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "mpconfig.h"
+#include "misc.h"
+#include "nlr.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "stackctrl.h"
+
+// Stack top at the start of program
+char *stack_top;
+
+void stack_ctrl_init() {
+ volatile int stack_dummy;
+ stack_top = (char*)&stack_dummy;
+}
+
+uint stack_usage() {
+ // Assumes descending stack
+ volatile int stack_dummy;
+ return stack_top - (char*)&stack_dummy;
+}
+
+#if MICROPY_STACK_CHECK
+
+uint stack_limit = 10240;
+
+void stack_set_limit(uint limit) {
+ stack_limit = limit;
+}
+
+void stack_check() {
+ if (stack_usage() >= stack_limit) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "maximum recursion depth exceeded"));
+ }
+}
+
+#endif // MICROPY_STACK_CHECK
diff --git a/py/stackctrl.h b/py/stackctrl.h
new file mode 100644
index 0000000000..a9a8d2e2d8
--- /dev/null
+++ b/py/stackctrl.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Paul Sokolovsky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+void stack_ctrl_init();
+uint stack_usage();
+
+#if MICROPY_STACK_CHECK
+
+void stack_set_limit(uint limit);
+void stack_check();
+#define STACK_CHECK() stack_check()
+
+#else
+
+#define stack_set_limit(limit)
+#define STACK_CHECK()
+
+#endif
diff --git a/py/unicode.c b/py/unicode.c
index c8faa57009..88f835131d 100644
--- a/py/unicode.c
+++ b/py/unicode.c
@@ -26,8 +26,8 @@
#include <stdint.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
// attribute flags
#define FL_PRINT (0x01)
diff --git a/py/vstr.c b/py/vstr.c
index ea6a1c937f..f8b7e4dabc 100644
--- a/py/vstr.c
+++ b/py/vstr.c
@@ -29,8 +29,8 @@
#include <stdarg.h>
#include <string.h>
#include <assert.h>
-#include "misc.h"
#include "mpconfig.h"
+#include "misc.h"
// returned value is always at least 1 greater than argument
#define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8)
diff --git a/stmhal/Makefile b/stmhal/Makefile
index e27dd7b6ce..3cc98d7be8 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -41,7 +41,7 @@ INC += -I$(FATFS_DIR)/src
INC += -I$(CC3K_DIR)
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
-CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) $(COPT)
+CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
CFLAGS += -Iboards/$(BOARD)
@@ -53,7 +53,7 @@ else
COPT += -Os -DNDEBUG
endif
-LDFLAGS = --nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref
+LDFLAGS = -nostdlib -T stm32f405.ld -Map=$(@:.elf=.map) --cref
LIBS =
# uncomment this if you want libgcc
diff --git a/stmhal/adc.c b/stmhal/adc.c
index 4930310fd3..c2419d543f 100644
--- a/stmhal/adc.c
+++ b/stmhal/adc.c
@@ -80,7 +80,7 @@ typedef struct _pyb_obj_adc_t {
ADC_HandleTypeDef handle;
} pyb_obj_adc_t;
-void adc_init_single(pyb_obj_adc_t *adc_obj) {
+STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
if (!IS_ADC_CHANNEL(adc_obj->channel)) {
return;
}
@@ -114,7 +114,9 @@ void adc_init_single(pyb_obj_adc_t *adc_obj) {
adcHandle->Init.EOCSelection = DISABLE;
HAL_ADC_Init(adcHandle);
+}
+STATIC void adc_config_channel(pyb_obj_adc_t *adc_obj) {
ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = adc_obj->channel;
@@ -122,10 +124,10 @@ void adc_init_single(pyb_obj_adc_t *adc_obj) {
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
sConfig.Offset = 0;
- HAL_ADC_ConfigChannel(adcHandle, &sConfig);
+ HAL_ADC_ConfigChannel(&adc_obj->handle, &sConfig);
}
-uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) {
+STATIC uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) {
uint32_t rawValue = 0;
HAL_ADC_Start(adcHandle);
@@ -193,6 +195,7 @@ STATIC mp_obj_t adc_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
STATIC mp_obj_t adc_read(mp_obj_t self_in) {
pyb_obj_adc_t *self = self_in;
+ adc_config_channel(self);
uint32_t data = adc_read_channel(&self->handle);
return mp_obj_new_int(data);
}
@@ -226,6 +229,7 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_
// This uses the timer in polling mode to do the sampling
// We could use DMA, but then we can't convert the values correctly for the buffer
+ adc_config_channel(self);
for (uint index = 0; index < bufinfo.len; index++) {
// Wait for the timer to trigger
while (__HAL_TIM_GET_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE) == RESET) {
diff --git a/stmhal/dac.c b/stmhal/dac.c
index 81ce993a8c..725e14e906 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -237,7 +237,7 @@ STATIC const mp_arg_t pyb_dac_write_timed_args[] = {
{ MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DMA_NORMAL} },
};
-#define PYB_DAC_WRITE_TIMED_NUM_ARGS ARRAY_SIZE(pyb_dac_write_timed_args)
+#define PYB_DAC_WRITE_TIMED_NUM_ARGS MP_ARRAY_SIZE(pyb_dac_write_timed_args)
mp_obj_t pyb_dac_write_timed(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_dac_obj_t *self = args[0];
diff --git a/stmhal/extint.c b/stmhal/extint.c
index 24d51ffb8d..591246cdd1 100644
--- a/stmhal/extint.c
+++ b/stmhal/extint.c
@@ -296,7 +296,7 @@ STATIC const mp_arg_t pyb_extint_make_new_args[] = {
{ MP_QSTR_pull, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
-#define PYB_EXTINT_MAKE_NEW_NUM_ARGS ARRAY_SIZE(pyb_extint_make_new_args)
+#define PYB_EXTINT_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(pyb_extint_make_new_args)
STATIC mp_obj_t extint_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// type_in == extint_obj_type
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index 00501a57da..b6ab531293 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -220,7 +220,7 @@ STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
{ MP_QSTR_gencall, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
-#define PYB_I2C_INIT_NUM_ARGS ARRAY_SIZE(pyb_i2c_init_args)
+#define PYB_I2C_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_init_args)
STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
@@ -271,7 +271,7 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
machine_int_t i2c_id = mp_obj_get_int(args[0]) - 1;
// check i2c number
- if (!(0 <= i2c_id && i2c_id < ARRAY_SIZE(pyb_i2c_obj) && pyb_i2c_obj[i2c_id].i2c != NULL)) {
+ if (!(0 <= i2c_id && i2c_id < MP_ARRAY_SIZE(pyb_i2c_obj) && pyb_i2c_obj[i2c_id].i2c != NULL)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C bus %d does not exist", i2c_id + 1));
}
@@ -363,7 +363,7 @@ STATIC const mp_arg_t pyb_i2c_send_args[] = {
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = PYB_I2C_MASTER_ADDRESS} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_I2C_SEND_NUM_ARGS ARRAY_SIZE(pyb_i2c_send_args)
+#define PYB_I2C_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_send_args)
STATIC mp_obj_t pyb_i2c_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
@@ -414,7 +414,7 @@ STATIC const mp_arg_t pyb_i2c_recv_args[] = {
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = PYB_I2C_MASTER_ADDRESS} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_I2C_RECV_NUM_ARGS ARRAY_SIZE(pyb_i2c_recv_args)
+#define PYB_I2C_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_recv_args)
STATIC mp_obj_t pyb_i2c_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
@@ -470,7 +470,7 @@ STATIC const mp_arg_t pyb_i2c_mem_read_args[] = {
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_I2C_MEM_READ_NUM_ARGS ARRAY_SIZE(pyb_i2c_mem_read_args)
+#define PYB_I2C_MEM_READ_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_mem_read_args)
STATIC mp_obj_t pyb_i2c_mem_read(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
diff --git a/stmhal/led.c b/stmhal/led.c
index 8cef02425a..c1b298b179 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -61,7 +61,7 @@ STATIC const pyb_led_obj_t pyb_led_obj[] = {
#endif
#endif
};
-#define NUM_LEDS ARRAY_SIZE(pyb_led_obj)
+#define NUM_LEDS MP_ARRAY_SIZE(pyb_led_obj)
void led_init(void) {
/* GPIO structure */
@@ -148,18 +148,9 @@ void led_toggle(pyb_led_t led) {
}
#endif
+ // toggle the output data register to toggle the LED state
const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin;
- GPIO_TypeDef *gpio = led_pin->gpio;
-
- // We don't know if we're turning the LED on or off, but we don't really
- // care. Just invert the state.
- if (gpio->ODR & led_pin->pin_mask) {
- // pin is high, make it low
- gpio->BSRRH = led_pin->pin_mask;
- } else {
- // pin is low, make it high
- gpio->BSRRL = led_pin->pin_mask;
- }
+ led_pin->gpio->ODR ^= led_pin->pin_mask;
}
int led_get_intensity(pyb_led_t led) {
diff --git a/stmhal/main.c b/stmhal/main.c
index 9751dcac2e..4e50daba41 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -40,6 +40,7 @@
#include "parse.h"
#include "obj.h"
#include "runtime.h"
+#include "stackctrl.h"
#include "gc.h"
#include "gccollect.h"
#include "pybstdio.h"
@@ -186,6 +187,11 @@ static const char fresh_readme_txt[] =
int main(void) {
// TODO disable JTAG
+ stack_ctrl_init();
+ // Stack limit should be less than real stack size, so we
+ // had chance to recover from limit hit.
+ stack_set_limit(&_ram_end - &_heap_end - 512);
+
/* STM32F4xx HAL library initialization:
- Configure the Flash prefetch, instruction and Data caches
- Configure the Systick to generate an interrupt each 1 msec
@@ -308,7 +314,7 @@ soft_reset:
MP_OBJ_NEW_SMALL_INT(115200),
};
pyb_uart_global_debug = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type,
- ARRAY_SIZE(args),
+ MP_ARRAY_SIZE(args),
0, args);
}
#else
diff --git a/stmhal/modos.c b/stmhal/modos.c
index 4a6949a844..e0df05ca6b 100644
--- a/stmhal/modos.c
+++ b/stmhal/modos.c
@@ -194,8 +194,8 @@ STATIC const mp_obj_dict_t os_module_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(os_module_globals_table),
- .alloc = ARRAY_SIZE(os_module_globals_table),
+ .used = MP_ARRAY_SIZE(os_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(os_module_globals_table),
.table = (mp_map_elem_t*)os_module_globals_table,
},
};
diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c
index 6879a2c1b7..9dcd0e76ca 100644
--- a/stmhal/modpyb.c
+++ b/stmhal/modpyb.c
@@ -426,8 +426,8 @@ STATIC const mp_obj_dict_t pyb_module_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(pyb_module_globals_table),
- .alloc = ARRAY_SIZE(pyb_module_globals_table),
+ .used = MP_ARRAY_SIZE(pyb_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(pyb_module_globals_table),
.table = (mp_map_elem_t*)pyb_module_globals_table,
},
};
diff --git a/stmhal/modstm.c b/stmhal/modstm.c
index 520c8e51bd..1196ff82ff 100644
--- a/stmhal/modstm.c
+++ b/stmhal/modstm.c
@@ -131,8 +131,8 @@ STATIC const mp_obj_dict_t stm_module_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(stm_module_globals_table),
- .alloc = ARRAY_SIZE(stm_module_globals_table),
+ .used = MP_ARRAY_SIZE(stm_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(stm_module_globals_table),
.table = (mp_map_elem_t*)stm_module_globals_table,
},
};
diff --git a/stmhal/modtime.c b/stmhal/modtime.c
index 4fbee31293..ea4e3210a6 100644
--- a/stmhal/modtime.c
+++ b/stmhal/modtime.c
@@ -122,8 +122,8 @@ STATIC const mp_obj_dict_t time_module_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(time_module_globals_table),
- .alloc = ARRAY_SIZE(time_module_globals_table),
+ .used = MP_ARRAY_SIZE(time_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(time_module_globals_table),
.table = (mp_map_elem_t*)time_module_globals_table,
},
};
diff --git a/stmhal/pin.c b/stmhal/pin.c
index 9806a8c49a..449b5074f4 100644
--- a/stmhal/pin.c
+++ b/stmhal/pin.c
@@ -100,8 +100,8 @@ STATIC mp_obj_t pin_class_map_dict;
STATIC bool pin_class_debug;
void pin_init(void) {
- pin_class_mapper = MP_OBJ_NULL;
- pin_class_map_dict = MP_OBJ_NULL;
+ pin_class_mapper = mp_const_none;
+ pin_class_map_dict = mp_const_none;
pin_class_debug = false;
}
@@ -120,7 +120,7 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
return pin_obj;
}
- if (pin_class_mapper != MP_OBJ_NULL) {
+ if (pin_class_mapper != mp_const_none) {
pin_obj = mp_call_function_1(pin_class_mapper, user_obj);
if (pin_obj != mp_const_none) {
if (!MP_OBJ_IS_TYPE(pin_obj, &pin_type)) {
@@ -139,7 +139,7 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
// other lookup methods.
}
- if (pin_class_map_dict != MP_OBJ_NULL) {
+ if (pin_class_map_dict != mp_const_none) {
mp_map_t *pin_map_map = mp_obj_dict_get_map(pin_class_map_dict);
mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP);
if (elem != NULL && elem->value != NULL) {
diff --git a/stmhal/spi.c b/stmhal/spi.c
index 10ecf7ec8e..448b8696ea 100644
--- a/stmhal/spi.c
+++ b/stmhal/spi.c
@@ -188,7 +188,7 @@ STATIC const pyb_spi_obj_t pyb_spi_obj[] = {
{{&pyb_spi_type}, NULL},
#endif
};
-#define PYB_NUM_SPI ARRAY_SIZE(pyb_spi_obj)
+#define PYB_NUM_SPI MP_ARRAY_SIZE(pyb_spi_obj)
STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_spi_obj_t *self = self_in;
@@ -242,7 +242,7 @@ STATIC const mp_arg_t pyb_spi_init_args[] = {
{ MP_QSTR_ti, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_crc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
-#define PYB_SPI_INIT_NUM_ARGS ARRAY_SIZE(pyb_spi_init_args)
+#define PYB_SPI_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_init_args)
STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
@@ -359,7 +359,7 @@ STATIC const mp_arg_t pyb_spi_send_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_SPI_SEND_NUM_ARGS ARRAY_SIZE(pyb_spi_send_args)
+#define PYB_SPI_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_send_args)
STATIC mp_obj_t pyb_spi_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
@@ -401,7 +401,7 @@ STATIC const mp_arg_t pyb_spi_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_SPI_RECV_NUM_ARGS ARRAY_SIZE(pyb_spi_recv_args)
+#define PYB_SPI_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_recv_args)
STATIC mp_obj_t pyb_spi_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
@@ -449,7 +449,7 @@ STATIC const mp_arg_t pyb_spi_send_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_SPI_SEND_RECV_NUM_ARGS ARRAY_SIZE(pyb_spi_send_recv_args)
+#define PYB_SPI_SEND_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_spi_send_recv_args)
STATIC mp_obj_t pyb_spi_send_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
diff --git a/stmhal/timer.c b/stmhal/timer.c
index 0ba24754b2..ec0c4dec4c 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -105,7 +105,7 @@ static uint32_t tim3_counter = 0;
// Used to do callbacks to Python code on interrupt
STATIC pyb_timer_obj_t *pyb_timer_obj_all[14];
-#define PYB_TIMER_OBJ_ALL_NUM ARRAY_SIZE(pyb_timer_obj_all)
+#define PYB_TIMER_OBJ_ALL_NUM MP_ARRAY_SIZE(pyb_timer_obj_all)
void timer_init0(void) {
tim3_counter = 0;
@@ -234,7 +234,7 @@ STATIC const mp_arg_t pyb_timer_init_args[] = {
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_COUNTERMODE_UP} },
{ MP_QSTR_div, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_CLOCKDIVISION_DIV1} },
};
-#define PYB_TIMER_INIT_NUM_ARGS ARRAY_SIZE(pyb_timer_init_args)
+#define PYB_TIMER_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_timer_init_args)
STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
diff --git a/stmhal/uart.c b/stmhal/uart.c
index 5bbd9f299e..a85f7f9e3a 100644
--- a/stmhal/uart.c
+++ b/stmhal/uart.c
@@ -270,7 +270,7 @@ STATIC const mp_arg_t pyb_uart_init_args[] = {
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
-#define PYB_UART_INIT_NUM_ARGS ARRAY_SIZE(pyb_uart_init_args)
+#define PYB_UART_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_init_args)
STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
@@ -396,7 +396,7 @@ STATIC const mp_arg_t pyb_uart_send_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_UART_SEND_NUM_ARGS ARRAY_SIZE(pyb_uart_send_args)
+#define PYB_UART_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_send_args)
STATIC mp_obj_t pyb_uart_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
@@ -438,7 +438,7 @@ STATIC const mp_arg_t pyb_uart_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
-#define PYB_UART_RECV_NUM_ARGS ARRAY_SIZE(pyb_uart_recv_args)
+#define PYB_UART_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_recv_args)
STATIC mp_obj_t pyb_uart_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
diff --git a/teensy/Makefile b/teensy/Makefile
index 00f3514724..8244d52d31 100644
--- a/teensy/Makefile
+++ b/teensy/Makefile
@@ -23,7 +23,7 @@ INC += -I$(PY_SRC)
INC += -I$(BUILD)
INC += -I$(CORE_PATH)
-CFLAGS = $(INC) -Wall -ansi -std=gnu99 $(CFLAGS_CORTEX_M4)
+CFLAGS = $(INC) -Wall -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4)
LDFLAGS = -nostdlib -T mk20dx256.ld
LIBS = -L $(COMPILER_PATH)/../lib/gcc/arm-none-eabi/4.7.2/thumb2 -lgcc
diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py
index b114a789b5..c3049c55d6 100644
--- a/tests/basics/struct1.py
+++ b/tests/basics/struct1.py
@@ -21,3 +21,7 @@ print(struct.calcsize("100sI"))
print(struct.calcsize("97sI"))
print(struct.unpack("<6sH", b"foo\0\0\0\x12\x34"))
print(struct.pack("<6sH", b"foo", 10000))
+
+s = struct.pack("BHBI", 10, 100, 200, 300)
+v = struct.unpack("BHBI", s)
+print(v == (10, 100, 200, 300))
diff --git a/tests/bench/arrayop-1-list_inplace.py b/tests/bench/arrayop-1-list_inplace.py
new file mode 100644
index 0000000000..0ee1ef2eca
--- /dev/null
+++ b/tests/bench/arrayop-1-list_inplace.py
@@ -0,0 +1,12 @@
+# Array operation
+# Type: list, inplace operation using for. What's good about this
+# method is that it doesn't require any extra memory allocation.
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ arr = [0] * 1000
+ for i in range(len(arr)):
+ arr[i] += 1
+
+bench.run(test)
diff --git a/tests/bench/arrayop-2-list_map.py b/tests/bench/arrayop-2-list_map.py
new file mode 100644
index 0000000000..9d5095c53a
--- /dev/null
+++ b/tests/bench/arrayop-2-list_map.py
@@ -0,0 +1,12 @@
+# Array operation
+# Type: list, map() call. This method requires allocation of
+# the same amount of memory as original array (to hold result
+# array). On the other hand, input array stays intact.
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ arr = [0] * 1000
+ arr2 = list(map(lambda x: x + 1, arr))
+
+bench.run(test)
diff --git a/tests/bench/arrayop-3-bytearray_inplace.py b/tests/bench/arrayop-3-bytearray_inplace.py
new file mode 100644
index 0000000000..a6d6280705
--- /dev/null
+++ b/tests/bench/arrayop-3-bytearray_inplace.py
@@ -0,0 +1,12 @@
+# Array operation
+# Type: bytearray, inplace operation using for. What's good about this
+# method is that it doesn't require any extra memory allocation.
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ arr = bytearray(b"\0" * 1000)
+ for i in range(len(arr)):
+ arr[i] += 1
+
+bench.run(test)
diff --git a/tests/bench/arrayop-4-bytearray_map.py b/tests/bench/arrayop-4-bytearray_map.py
new file mode 100644
index 0000000000..1b92a40961
--- /dev/null
+++ b/tests/bench/arrayop-4-bytearray_map.py
@@ -0,0 +1,12 @@
+# Array operation
+# Type: list, map() call. This method requires allocation of
+# the same amount of memory as original array (to hold result
+# array). On the other hand, input array stays intact.
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ arr = bytearray(b"\0" * 1000)
+ arr2 = bytearray(map(lambda x: x + 1, arr))
+
+bench.run(test)
diff --git a/tests/bench/bytebuf-1-inplace.py b/tests/bench/bytebuf-1-inplace.py
new file mode 100644
index 0000000000..7e7d9391cc
--- /dev/null
+++ b/tests/bench/bytebuf-1-inplace.py
@@ -0,0 +1,11 @@
+# Doing some operation on bytearray
+# Inplace - the most memory efficient way
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ ba = bytearray(b"\0" * 1000)
+ for i in range(len(ba)):
+ ba[i] += 1
+
+bench.run(test)
diff --git a/tests/bench/bytebuf-2-join_map_bytes.py b/tests/bench/bytebuf-2-join_map_bytes.py
new file mode 100644
index 0000000000..daa622991f
--- /dev/null
+++ b/tests/bench/bytebuf-2-join_map_bytes.py
@@ -0,0 +1,12 @@
+# Doing some operation on bytearray
+# Pretty weird way - map bytearray thru function, but make sure that
+# function return bytes of size 1, then join them together. Surely,
+# this is slowest way to do it.
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ ba = bytearray(b"\0" * 1000)
+ ba2 = b''.join(map(lambda x:bytes([x + 1]), ba))
+
+bench.run(test)
diff --git a/tests/bench/bytebuf-3-bytarray_map.py b/tests/bench/bytebuf-3-bytarray_map.py
new file mode 100644
index 0000000000..078d08e99b
--- /dev/null
+++ b/tests/bench/bytebuf-3-bytarray_map.py
@@ -0,0 +1,10 @@
+# Doing some operation on bytearray
+# No joins, but still map().
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ ba = bytearray(b"\0" * 1000)
+ ba2 = bytearray(map(lambda x: x + 1, ba))
+
+bench.run(test)
diff --git a/tests/bench/from_iter-1-list_bound.py b/tests/bench/from_iter-1-list_bound.py
new file mode 100644
index 0000000000..d209daecc5
--- /dev/null
+++ b/tests/bench/from_iter-1-list_bound.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ l = [0] * 1000
+ l2 = list(l)
+
+bench.run(test)
diff --git a/tests/bench/from_iter-2-list_unbound.py b/tests/bench/from_iter-2-list_unbound.py
new file mode 100644
index 0000000000..be019c52fe
--- /dev/null
+++ b/tests/bench/from_iter-2-list_unbound.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ l = [0] * 1000
+ l2 = list(map(lambda x: x, l))
+
+bench.run(test)
diff --git a/tests/bench/from_iter-3-tuple_bound.py b/tests/bench/from_iter-3-tuple_bound.py
new file mode 100644
index 0000000000..7b7fa36c6e
--- /dev/null
+++ b/tests/bench/from_iter-3-tuple_bound.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ l = [0] * 1000
+ l2 = tuple(l)
+
+bench.run(test)
diff --git a/tests/bench/from_iter-4-tuple_unbound.py b/tests/bench/from_iter-4-tuple_unbound.py
new file mode 100644
index 0000000000..7c7f134c85
--- /dev/null
+++ b/tests/bench/from_iter-4-tuple_unbound.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ l = [0] * 1000
+ l2 = tuple(map(lambda x: x, l))
+
+bench.run(test)
diff --git a/tests/bench/from_iter-5-bytes_bound.py b/tests/bench/from_iter-5-bytes_bound.py
new file mode 100644
index 0000000000..b793a3207e
--- /dev/null
+++ b/tests/bench/from_iter-5-bytes_bound.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ l = [0] * 1000
+ l2 = bytes(l)
+
+bench.run(test)
diff --git a/tests/bench/from_iter-6-bytes_unbound.py b/tests/bench/from_iter-6-bytes_unbound.py
new file mode 100644
index 0000000000..20aa556277
--- /dev/null
+++ b/tests/bench/from_iter-6-bytes_unbound.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ l = [0] * 1000
+ l2 = bytes(map(lambda x: x, l))
+
+bench.run(test)
diff --git a/tests/bench/from_iter-7-bytearray_bound.py b/tests/bench/from_iter-7-bytearray_bound.py
new file mode 100644
index 0000000000..72001a05c7
--- /dev/null
+++ b/tests/bench/from_iter-7-bytearray_bound.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ l = [0] * 1000
+ l2 = bytearray(l)
+
+bench.run(test)
diff --git a/tests/bench/from_iter-8-bytearray_unbound.py b/tests/bench/from_iter-8-bytearray_unbound.py
new file mode 100644
index 0000000000..e2263b8ef9
--- /dev/null
+++ b/tests/bench/from_iter-8-bytearray_unbound.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ for i in iter(range(num//10000)):
+ l = [0] * 1000
+ l2 = bytearray(map(lambda x: x, l))
+
+bench.run(test)
diff --git a/tests/bench/funcall-1-inline.py b/tests/bench/funcall-1-inline.py
new file mode 100644
index 0000000000..fbeb79630d
--- /dev/null
+++ b/tests/bench/funcall-1-inline.py
@@ -0,0 +1,9 @@
+# Function call overhead test
+# Establish a baseline for performing a trivial operation inline
+import bench
+
+def test(num):
+ for i in iter(range(num)):
+ a = i + 1
+
+bench.run(test)
diff --git a/tests/bench/funcall-2-funcall.py b/tests/bench/funcall-2-funcall.py
new file mode 100644
index 0000000000..d5c36c60aa
--- /dev/null
+++ b/tests/bench/funcall-2-funcall.py
@@ -0,0 +1,12 @@
+# Function call overhead test
+# Perform the same trivial operation as global function call
+import bench
+
+def f(x):
+ return x + 1
+
+def test(num):
+ for i in iter(range(num)):
+ a = f(i)
+
+bench.run(test)
diff --git a/tests/bench/funcall-3-funcall-local.py b/tests/bench/funcall-3-funcall-local.py
new file mode 100644
index 0000000000..1a6d728c63
--- /dev/null
+++ b/tests/bench/funcall-3-funcall-local.py
@@ -0,0 +1,16 @@
+# Function call overhead test
+# Perform the same trivial operation as calling function, cached in a
+# local variable. This is commonly known optimization for overly dynamic
+# languages (the idea is to cut on symbolic look up overhead, as local
+# variables are accessed by offset, not by name)
+import bench
+
+def f(x):
+ return x + 1
+
+def test(num):
+ f_ = f
+ for i in iter(range(num)):
+ a = f_(i)
+
+bench.run(test)
diff --git a/tests/float/math-fun-bool.py b/tests/float/math-fun-bool.py
index cf718d4b80..57232857ab 100644
--- a/tests/float/math-fun-bool.py
+++ b/tests/float/math-fun-bool.py
@@ -1,6 +1,11 @@
# Test the bool functions from math
-from math import isfinite, isnan, isinf
+try:
+ from math import isfinite, isnan, isinf
+except ImportError:
+ print("SKIP")
+ import sys
+ sys.exit()
test_values = [1, 0, -1, 1.0, 0.0, -1.0, float('NaN'), float('Inf'),
-float('NaN'), -float('Inf')]
diff --git a/tests/float/math-fun.py b/tests/float/math-fun.py
index 7a37c58454..fa111e33e3 100644
--- a/tests/float/math-fun.py
+++ b/tests/float/math-fun.py
@@ -1,6 +1,11 @@
# Tests the functions imported from math
-from math import *
+try:
+ from math import *
+except ImportError:
+ print("SKIP")
+ import sys
+ sys.exit()
test_values = [-100., -1.23456, -1, -0.5, 0.0, 0.5, 1.23456, 100.]
p_test_values = [0.1, 0.5, 1.23456]
diff --git a/tests/misc/recursion.py b/tests/misc/recursion.py
new file mode 100644
index 0000000000..227f48396a
--- /dev/null
+++ b/tests/misc/recursion.py
@@ -0,0 +1,7 @@
+def foo():
+ foo()
+
+try:
+ foo()
+except RuntimeError:
+ print("RuntimeError")
diff --git a/unix/Makefile b/unix/Makefile
index 485009135f..afe268ae45 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -7,6 +7,9 @@ PROG = micropython
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
+# OS name, for simple autoconfig
+UNAME_S := $(shell uname -s)
+
# include py core make definitions
include ../py/py.mk
@@ -15,14 +18,18 @@ INC += -I$(PY_SRC)
INC += -I$(BUILD)
# compiler settings
-CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT)
+CWARN = -Wall -Werror -Wno-error=cpp
+CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
-UNAME_S := $(shell uname -s)
- ifeq ($(UNAME_S),Darwin)
- LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-map,$@.map,-order_file,$(BUILD)/order.def
- else
- LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref
- endif
+# Debugging/Optimization
+ifdef DEBUG
+CFLAGS += -g
+COPT = -O0
+else
+COPT = -Os #-DNDEBUG
+endif
+
+LDFLAGS = $(LDFLAGS_MOD) -lm -Wl,-Map=$@.map,--cref $(LDFLAGS_EXTRA)
ifeq ($(MICROPY_FORCE_32BIT),1)
CFLAGS += -m32
@@ -56,14 +63,6 @@ SRC_MOD += modffi.c
endif
-# Debugging/Optimization
-ifdef DEBUG
-CFLAGS += -g
-COPT = -O0
-else
-COPT = -Os #-DNDEBUG
-endif
-
# source files
SRC_C = \
main.c \
@@ -75,6 +74,9 @@ SRC_C = \
$(SRC_MOD)
ifeq ($(UNAME_S),Darwin)
+
+LDFLAGS+ = -Wl,-order_file,$(BUILD)/order.def
+
# Must be the last file in list of sources
SRC_C += seg_helpers.c
diff --git a/unix/gccollect.c b/unix/gccollect.c
index 4f3b786e72..f24cc52495 100644
--- a/unix/gccollect.c
+++ b/unix/gccollect.c
@@ -97,7 +97,7 @@ void gc_helper_get_regs(regs_t arr) {
}
#endif
-#ifdef __thumb2__
+#if defined(__thumb2__) || defined(__thumb__) || defined(__arm__)
typedef machine_uint_t regs_t[10];
void gc_helper_get_regs(regs_t arr) {
@@ -130,8 +130,11 @@ void gc_collect(void) {
gc_collect_start();
// this traces the .bss section
-#ifdef __CYGWIN__
+#if defined( __CYGWIN__ )
#define BSS_START __bss_start__
+#elif defined( _MSC_VER ) || defined( __MINGW32__ )
+#define BSS_START *bss_start
+#define _end *bss_end
#else
#define BSS_START __bss_start
#endif
@@ -141,7 +144,8 @@ void gc_collect(void) {
regs_t regs;
gc_helper_get_regs(regs);
// GC stack (and regs because we captured them)
- gc_collect_root((void**)&regs, ((machine_uint_t)stack_top - (machine_uint_t)&regs) / sizeof(machine_uint_t));
+ void **regs_ptr = (void**)(void*)&regs;
+ gc_collect_root(regs_ptr, ((machine_uint_t)stack_top - (machine_uint_t)&regs) / sizeof(machine_uint_t));
gc_collect_end();
//printf("-----\n");
diff --git a/unix/main.c b/unix/main.c
index 26736e4318..a08661339c 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -51,6 +51,7 @@
#include "gc.h"
#include "genhdr/py-version.h"
#include "input.h"
+#include "stackctrl.h"
// Command line options, with their defaults
bool compile_only = false;
@@ -63,9 +64,6 @@ uint mp_verbose_flag;
long heap_size = 128*1024 * (sizeof(machine_uint_t) / 4);
#endif
-// Stack top at the start of program
-char *stack_top;
-
void microsocket_init();
void time_init();
void ffi_init();
@@ -201,8 +199,8 @@ int usage(char **argv) {
impl_opts_cnt++;
#if MICROPY_ENABLE_GC
printf(
-" heapsize=<n> -- set the heap size for the GC\n"
-);
+" heapsize=<n> -- set the heap size for the GC (default %ld)\n"
+, heap_size);
impl_opts_cnt++;
#endif
@@ -214,10 +212,9 @@ int usage(char **argv) {
}
mp_obj_t mem_info(void) {
- volatile int stack_dummy;
printf("mem: total=%d, current=%d, peak=%d\n",
m_get_total_bytes_allocated(), m_get_current_bytes_allocated(), m_get_peak_bytes_allocated());
- printf("stack: " INT_FMT "\n", stack_top - (char*)&stack_dummy);
+ printf("stack: %u\n", stack_usage());
#if MICROPY_ENABLE_GC
gc_dump_info();
#endif
@@ -268,8 +265,8 @@ void pre_process_options(int argc, char **argv) {
#endif
int main(int argc, char **argv) {
- volatile int stack_dummy;
- stack_top = (char*)&stack_dummy;
+ stack_ctrl_init();
+ stack_set_limit(32768);
pre_process_options(argc, argv);
@@ -365,7 +362,8 @@ int main(int argc, char **argv) {
return usage(argv);
}
} else {
- char *basedir = realpath(argv[a], NULL);
+ char *pathbuf = malloc(PATH_MAX);
+ char *basedir = realpath(argv[a], pathbuf);
if (basedir == NULL) {
fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[a], errno);
perror("");
@@ -377,7 +375,7 @@ int main(int argc, char **argv) {
// Set base dir of the script as first entry in sys.path
char *p = strrchr(basedir, '/');
path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir));
- free(basedir);
+ free(pathbuf);
for (int i = a; i < argc; i++) {
mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
diff --git a/unix/modffi.c b/unix/modffi.c
index bfc840ceff..f1b219987b 100644
--- a/unix/modffi.c
+++ b/unix/modffi.c
@@ -421,8 +421,8 @@ STATIC const mp_obj_dict_t mp_module_ffi_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_ffi_globals_table),
- .alloc = ARRAY_SIZE(mp_module_ffi_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_ffi_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_ffi_globals_table),
.table = (mp_map_elem_t*)mp_module_ffi_globals_table,
},
};
diff --git a/unix/modos.c b/unix/modos.c
index 657958d04c..2e02ef0aa7 100644
--- a/unix/modos.c
+++ b/unix/modos.c
@@ -75,8 +75,8 @@ STATIC const mp_obj_dict_t mp_module_os_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_os_globals_table),
- .alloc = ARRAY_SIZE(mp_module_os_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_os_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_os_globals_table),
.table = (mp_map_elem_t*)mp_module_os_globals_table,
},
};
diff --git a/unix/modsocket.c b/unix/modsocket.c
index b1a34a39b8..5b3fb01877 100644
--- a/unix/modsocket.c
+++ b/unix/modsocket.c
@@ -356,6 +356,8 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
const char *host = mp_obj_str_get_str(args[0]);
const char *serv = NULL;
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
// getaddrinfo accepts port in string notation, so however
// it may seem stupid, we need to convert int to str
if (MP_OBJ_IS_SMALL_INT(args[1])) {
@@ -363,23 +365,35 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
char buf[6];
sprintf(buf, "%d", port);
serv = buf;
+ hints.ai_flags = AI_NUMERICSERV;
+#ifdef __UCLIBC_MAJOR__
+#if __UCLIBC_MAJOR__ == 0 && (__UCLIBC_MINOR__ < 9 || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 32))
+#warning Working around uClibc bug with numeric service name
+ // Older versions og uClibc have bugs when numeric ports in service
+ // arg require also hints.ai_socktype (or hints.ai_protocol) != 0
+ // This actually was fixed in 0.9.32.1, but uClibc doesn't allow to
+ // test for that.
+ // http://git.uclibc.org/uClibc/commit/libc/inet/getaddrinfo.c?id=bc3be18145e4d5
+ // Note that this is crude workaround, precluding UDP socket addresses
+ // to be returned. TODO: set only if not set by Python args.
+ hints.ai_socktype = SOCK_STREAM;
+#endif
+#endif
} else {
serv = mp_obj_str_get_str(args[1]);
}
- struct addrinfo hints;
- struct addrinfo *addr;
- memset(&hints, 0, sizeof(hints));
- int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr);
+ struct addrinfo *addr_list;
+ int res = getaddrinfo(host, serv, &hints, &addr_list);
if (res != 0) {
// CPython: socket.gaierror
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res));
}
- assert(addr);
+ assert(addr_list);
mp_obj_t list = mp_obj_new_list(0, NULL);
- for (; addr; addr = addr->ai_next) {
+ for (struct addrinfo *addr = addr_list; addr; addr = addr->ai_next) {
mp_obj_tuple_t *t = mp_obj_new_tuple(5, NULL);
t->items[0] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_family);
t->items[1] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_socktype);
@@ -394,6 +408,7 @@ STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr);
mp_obj_list_append(list, t);
}
+ freeaddrinfo(addr_list);
return list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 6, mod_socket_getaddrinfo);
@@ -436,8 +451,8 @@ STATIC const mp_obj_dict_t mp_module_socket_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_socket_globals_table),
- .alloc = ARRAY_SIZE(mp_module_socket_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_socket_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_socket_globals_table),
.table = (mp_map_elem_t*)mp_module_socket_globals_table,
},
};
diff --git a/unix/modtime.c b/unix/modtime.c
index 3cc09e3cd8..006fd0ebd7 100644
--- a/unix/modtime.c
+++ b/unix/modtime.c
@@ -113,8 +113,8 @@ STATIC const mp_obj_dict_t mp_module_time_globals = {
.map = {
.all_keys_are_qstrs = 1,
.table_is_fixed_array = 1,
- .used = ARRAY_SIZE(mp_module_time_globals_table),
- .alloc = ARRAY_SIZE(mp_module_time_globals_table),
+ .used = MP_ARRAY_SIZE(mp_module_time_globals_table),
+ .alloc = MP_ARRAY_SIZE(mp_module_time_globals_table),
.table = (mp_map_elem_t*)mp_module_time_globals_table,
},
};
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 3426ae44fe..1559bdb359 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -53,7 +53,9 @@
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED)
// Define to 1 to use untested inefficient GC helper implementation
// (if more efficient arch-specific one is not available).
+#ifndef MICROPY_GCREGS_SETJMP
#define MICROPY_GCREGS_SETJMP (0)
+#endif
extern const struct _mp_obj_module_t mp_module_os;
extern const struct _mp_obj_module_t mp_module_time;
diff --git a/windows/Makefile b/windows/Makefile
index a188979bd5..e3085ff23b 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -35,9 +35,11 @@ SRC_C = \
unix/file.c \
unix/input.c \
unix/modtime.c \
+ unix/gccollect.c \
realpath.c \
init.c \
sleep.c \
+ bss.c \
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
diff --git a/windows/bss.c b/windows/bss.c
new file mode 100644
index 0000000000..b860c4ee85
--- /dev/null
+++ b/windows/bss.c
@@ -0,0 +1,74 @@
+/*
+* This file is part of the Micro Python project, http://micropython.org/
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2013, 2014 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
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+#include "mpconfig.h"
+#include "misc.h"
+#include "nlr.h"
+#include "qstr.h"
+#include "obj.h"
+#include <windows.h>
+
+IMAGE_NT_HEADERS *header_from_memory(const char *module) {
+ BYTE *base_addr = (BYTE*)GetModuleHandleA(module);
+ IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER*)base_addr;
+ return (IMAGE_NT_HEADERS*)(base_addr + dos_header->e_lfanew);
+}
+
+IMAGE_SECTION_HEADER *find_section(IMAGE_NT_HEADERS *nt_header, const char *name) {
+ int i;
+ IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION(nt_header);
+ for (i = 0; i < nt_header->FileHeader.NumberOfSections; ++i) {
+ if (strcmp((const char *)section->Name, name) == 0) {
+ return section;
+ }
+ ++section;
+ }
+ return NULL;
+}
+
+void section_boundaries(IMAGE_NT_HEADERS *nt_header, IMAGE_SECTION_HEADER *section, char **start, char **end) {
+ if (section == NULL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Could not lookup section boundaries"));
+ }
+ *start = (char*)(nt_header->OptionalHeader.ImageBase + section->VirtualAddress);
+ *end = *start + section->Misc.VirtualSize;
+}
+
+void section_boundaries_from_module(const char *module, const char *section, char **start, char **end) {
+ IMAGE_NT_HEADERS *nt_header = header_from_memory(module);
+ IMAGE_SECTION_HEADER *dsection = find_section(nt_header, section);
+ section_boundaries(nt_header, dsection, start, end);
+}
+
+char *bss_start = 0;
+char *bss_end = 0;
+
+//MSVC has no __bss_start and _end but we can get accurate section info from the PE header.
+//The standard .bss section is appended to the standard .data section however so it cannot
+//be looked up by name. To deal with that we put all uPy static variables in a named section.
+void getbss() {
+ section_boundaries_from_module(NULL, MICROPY_PORT_BSSSECTION, &bss_start, &bss_end);
+}
diff --git a/windows/init.c b/windows/init.c
index a370c464e8..57f349ef89 100644
--- a/windows/init.c
+++ b/windows/init.c
@@ -28,9 +28,12 @@
#include <stdio.h>
#include <windows.h>
+extern void getbss();
+
HANDLE hSleepEvent = NULL;
void init() {
+ getbss();
hSleepEvent = CreateEvent(NULL, TRUE, FALSE, FALSE);
#ifdef __MINGW32__
putenv("PRINTF_EXPONENT_DIGITS=2");
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index b9a50b0841..c930fe95e8 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -43,6 +43,12 @@
#define MICROPY_PY_CMATH (1)
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_SYS_EXIT (1)
+#define MICROPY_ENABLE_GC (1)
+#define MICROPY_ENABLE_FINALISER (1)
+#define MICROPY_PY_GC_COLLECT_RETVAL (1)
+#ifdef _MSC_VER
+#define MICROPY_GCREGS_SETJMP (1)
+#endif
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_PORT_INIT_FUNC init()
@@ -113,6 +119,14 @@ void msec_sleep(double msec);
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+// Put static/global variables in sections with a known name we can lookup for the GC
+// For this to work this header must be included by all sources, which is the case normally
+#define MICROPY_PORT_DATASECTION "upydata"
+#define MICROPY_PORT_BSSSECTION "upybss"
+#pragma data_seg(MICROPY_PORT_DATASECTION)
+#pragma bss_seg(MICROPY_PORT_BSSSECTION)
+
+
// System headers (needed e.g. for nlr.h)
#include <stddef.h> //for NULL
@@ -122,3 +136,8 @@ void msec_sleep(double msec);
int snprintf(char *dest, size_t count, const char *format, ...);
#endif
+
+// MingW specifics
+#ifdef __MINGW32__
+#define MICROPY_PORT_BSSSECTION ".bss"
+#endif
diff --git a/windows/msvc/common.props b/windows/msvc/common.props
index 300de46a53..b6f22c6151 100644
--- a/windows/msvc/common.props
+++ b/windows/msvc/common.props
@@ -16,7 +16,8 @@
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
+ <GenerateMapFile>true</GenerateMapFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
-</Project> \ No newline at end of file
+</Project>
diff --git a/windows/msvc/sources.props b/windows/msvc/sources.props
index 8af03e7563..6fd3306b92 100644
--- a/windows/msvc/sources.props
+++ b/windows/msvc/sources.props
@@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<ClCompile Include="$(PyBaseDir)py\*.c" />
- <ClCompile Include="$(PyBaseDir)unix\*.c" Exclude="$(PyBaseDir)unix\modffi.c;$(PyBaseDir)unix\modsocket.c" />
+ <ClCompile Include="$(PyBaseDir)unix\*.c" Exclude="$(PyBaseDir)unix\modffi.c;$(PyBaseDir)unix\modsocket.c;$(PyBaseDir)unix\seg_helpers.c" />
<ClCompile Include="$(PyBaseDir)windows\*.c" />
<ClCompile Include="$(PyBaseDir)windows\msvc\*.c" />
</ItemGroup>