diff --git a/examples/natmod/deflate/deflate.c b/examples/natmod/deflate/deflate.c index 9de7e101a7689..56ce8c8385e92 100644 --- a/examples/natmod/deflate/deflate.c +++ b/examples/natmod/deflate/deflate.c @@ -68,3 +68,20 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a MP_DYNRUNTIME_INIT_EXIT } + +// On x86 and x64 (at least) Clang brings in its own memset() implementation, +// which will check at runtime which CPU features are available and then pick +// the fastest implementation depending on the running environment. +// +// This unfortunately includes a series of dependencies that do have a +// non-empty data section, which is currently not supported. Therefore if we +// detect Clang we provide our own naïve memset implementation. + +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) +__attribute__((weak)) void *memset(void *pointer, int character, size_t length) { + for (size_t index = 0; index < length; ++index) { + ((char *)pointer)[index] = (char)character; + } + return pointer; +} +#endif diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c index 5fd7c6be3a456..c1f414ead23d7 100644 --- a/examples/natmod/framebuf/framebuf.c +++ b/examples/natmod/framebuf/framebuf.c @@ -52,3 +52,20 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a MP_DYNRUNTIME_INIT_EXIT } + +// On x86 and x64 (at least) Clang brings in its own memset() implementation, +// which will check at runtime which CPU features are available and then pick +// the fastest implementation depending on the running environment. +// +// This unfortunately includes a series of dependencies that do have a +// non-empty data section, which is currently not supported. Therefore if we +// detect Clang we provide our own naïve memset implementation. + +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) +__attribute__((weak)) void *memset(void *pointer, int character, size_t length) { + for (size_t index = 0; index < length; ++index) { + ((char *)pointer)[index] = (char)character; + } + return pointer; +} +#endif diff --git a/examples/natmod/re/re.c b/examples/natmod/re/re.c index c0279ee7e816d..f9b9fd1de382d 100644 --- a/examples/natmod/re/re.c +++ b/examples/natmod/re/re.c @@ -89,3 +89,20 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a MP_DYNRUNTIME_INIT_EXIT } + +// On x86 and x64 (at least) Clang brings in its own memset() implementation, +// which will check at runtime which CPU features are available and then pick +// the fastest implementation depending on the running environment. +// +// This unfortunately includes a series of dependencies that do have a +// non-empty data section, which is currently not supported. Therefore if we +// detect Clang we provide our own naïve memset implementation. + +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) +__attribute__((weak)) void *memset(void *pointer, int character, size_t length) { + for (size_t index = 0; index < length; ++index) { + ((char *)pointer)[index] = (char)character; + } + return pointer; +} +#endif diff --git a/py/dynruntime.mk b/py/dynruntime.mk index 3902acbd0b32a..e544c7c0c8c40 100644 --- a/py/dynruntime.mk +++ b/py/dynruntime.mk @@ -2,6 +2,7 @@ # MPY_DIR must be set to the top of the MicroPython source tree BUILD ?= build +CC ?= gcc ECHO = @echo RM = /bin/rm @@ -104,13 +105,15 @@ MICROPY_FLOAT_IMPL ?= float else ifeq ($(ARCH),rv32imc) # rv32imc +ifeq ($(firstword $(shell $(CC) --version)),gcc) CROSS = riscv64-unknown-elf- +endif CFLAGS_ARCH += -march=rv32imac -mabi=ilp32 -mno-relax # If Picolibc is available then select it explicitly. Ubuntu 24.04 ships its # bare metal RISC-V toolchain with Picolibc rather than Newlib, and the default # is "nosys" so a value must be provided. To avoid having per-distro # workarounds, always select Picolibc if available. -PICOLIBC_SPECS := $(shell $(CROSS)gcc --print-file-name=picolibc.specs) +PICOLIBC_SPECS := $(shell $(CROSS)$(CC) --print-file-name=picolibc.specs) ifneq ($(PICOLIBC_SPECS),picolibc.specs) CFLAGS_ARCH += -specs=$(PICOLIBC_SPECS) USE_PICOLIBC := 1 @@ -123,13 +126,15 @@ MICROPY_FLOAT_IMPL ?= none else ifeq ($(ARCH),rv64imc) # rv64imc +ifeq ($(firstword $(shell $(CC) --version)),gcc) CROSS = riscv64-unknown-elf- +endif CFLAGS_ARCH += -march=rv64imac -mabi=lp64 -mno-relax # If Picolibc is available then select it explicitly. Ubuntu 24.04 ships its # bare metal RISC-V toolchain with Picolibc rather than Newlib, and the default # is "nosys" so a value must be provided. To avoid having per-distro # workarounds, always select Picolibc if available. -PICOLIBC_SPECS := $(shell $(CROSS)gcc --print-file-name=picolibc.specs) +PICOLIBC_SPECS := $(shell $(CROSS)$(CC) --print-file-name=picolibc.specs) ifneq ($(PICOLIBC_SPECS),picolibc.specs) CFLAGS_ARCH += -specs=$(PICOLIBC_SPECS) USE_PICOLIBC := 1 @@ -143,7 +148,11 @@ else $(error architecture '$(ARCH)' not supported) endif -ifneq ($(findstring -musl,$(shell $(CROSS)gcc -dumpmachine)),) +ifeq ($(findstring clang,$(shell $(CC) --version)),clang) +CROSS = +endif + +ifneq ($(findstring -musl,$(shell $(CROSS)$(CC) -dumpmachine)),) USE_MUSL := 1 endif @@ -175,8 +184,8 @@ LIBM_NAME := libc.a else LIBM_NAME := libm.a endif -LIBGCC_PATH := $(realpath $(shell $(CROSS)gcc $(CFLAGS) --print-libgcc-file-name)) -LIBM_PATH := $(realpath $(shell $(CROSS)gcc $(CFLAGS) --print-file-name=$(LIBM_NAME))) +LIBGCC_PATH := $(realpath $(shell $(CROSS)$(CC) $(CFLAGS) --print-libgcc-file-name)) +LIBM_PATH := $(realpath $(shell $(CROSS)$(CC) $(CFLAGS) --print-file-name=$(LIBM_NAME))) ifeq ($(USE_PICOLIBC),1) ifeq ($(LIBM_PATH),) # The CROSS toolchain prefix usually ends with a dash, but that may not be @@ -224,12 +233,12 @@ $(CONFIG_H): $(SRC) # Build .o from .c source files $(BUILD)/%.o: %.c $(CONFIG_H) Makefile $(ECHO) "CC $<" - $(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $< + $(Q)$(CROSS)$(CC) $(CFLAGS) -o $@ -c $< # Build .o from .S source files $(BUILD)/%.o: %.S $(CONFIG_H) Makefile $(ECHO) "AS $<" - $(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $< + $(Q)$(CROSS)$(CC) $(CFLAGS) -o $@ -c $< # Build .mpy from .py source files $(BUILD)/%.mpy: %.py diff --git a/py/mpconfig.h b/py/mpconfig.h index 1574243e8ea99..277ab9d7a4a2b 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -192,14 +192,18 @@ #endif #if MP_INT_TYPE == MP_INT_TYPE_INTPTR +#if !defined(MP_INT_TYPES_DEFINED) typedef intptr_t mp_int_t; typedef uintptr_t mp_uint_t; +#endif #define MP_INT_MAX INTPTR_MAX #define MP_INT_MIN INTPTR_MIN #define MP_UINT_MAX INTPTR_UMAX #elif MP_INT_TYPE == MP_INT_TYPE_INT64 +#if !defined(MP_INT_TYPES_DEFINED) typedef int64_t mp_int_t; typedef uint64_t mp_uint_t; +#endif #define MP_INT_MAX INT64_MAX #define MP_INT_MIN INT64_MIN #define MP_UINT_MAX INT64_UMAX diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index 20d665ff8849f..7cbe521aba67c 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -1509,7 +1509,8 @@ def do_preprocess(args): "#include \n" "typedef uintptr_t mp_uint_t;\n" "typedef intptr_t mp_int_t;\n" - "typedef uintptr_t mp_off_t;", + "typedef uintptr_t mp_off_t;\n" + "#define MP_INT_TYPES_DEFINED", file=f, ) for i, q in enumerate(static_qstrs):