From 59c24bec1f7fa6d753814fca66fb805fce763c5a Mon Sep 17 00:00:00 2001 From: Stas Boukarev Date: Wed, 22 Apr 2026 18:12:23 +0300 Subject: [PATCH 1/8] Fix base-char-p on known characters It needs to call ECL_BASE_CHAR_CODE_P. Fixes #812 --- src/cmp/cmpbackend-cxx/cmpc-inl-sysfun.lsp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmp/cmpbackend-cxx/cmpc-inl-sysfun.lsp b/src/cmp/cmpbackend-cxx/cmpc-inl-sysfun.lsp index 5f2c9074b..bf3c0fd03 100644 --- a/src/cmp/cmpbackend-cxx/cmpc-inl-sysfun.lsp +++ b/src/cmp/cmpbackend-cxx/cmpc-inl-sysfun.lsp @@ -636,7 +636,8 @@ (def-inline cl:integerp :always (t) :bool "@0;ECL_FIXNUMP(#0)||ECL_BIGNUMP(#0)") (def-inline cl:floatp :always (t) :bool "floatp(#0)") (def-inline cl:characterp :always (t) :bool "ECL_CHARACTERP(#0)") - (def-inline si:base-char-p :always (character) :bool "ECL_BASE_CHAR_P(#0)") + (def-inline si:base-char-p :always (t) :bool "ECL_BASE_CHAR_P(#0)") + (def-inline si:base-char-p :always (character) :bool "ECL_BASE_CHAR_CODE_P(#0)") (def-inline cl:stringp :always (t) :bool "@0;ECL_STRINGP(#0)") (def-inline si:base-string-p :always (t) :bool "@0;ECL_BASE_STRING_P(#0)") (def-inline cl:bit-vector-p :always (t) :bool "@0;ECL_BIT_VECTOR_P(#0)") From a0776503674d332443a4284b19816f56d8697235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Sun, 26 Apr 2026 10:17:50 +0200 Subject: [PATCH 2/8] stacks: disable some optimizations on clang (<= 17 +version+ 22) clang miscompiles some functions since the version 17; we bump the version from 19 to 22, because it was confirmed that it is still the case. Fixes #838. --- src/c/stacks.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/c/stacks.d b/src/c/stacks.d index ef52372c6..08d49aeb4 100644 --- a/src/c/stacks.d +++ b/src/c/stacks.d @@ -281,7 +281,7 @@ ecl_stack_frame_open(cl_env_ptr env, cl_object f, cl_index size) /* Some clang versions miscompile the following function on x86_64. * Temporarily turn off optimizations here. */ -#if defined(__clang__) && __clang_major__ >= 17 && __clang_major__ <= 19 && defined(__x86_64__) +#if defined(__clang__) && __clang_major__ >= 17 && __clang_major__ <= 22 && defined(__x86_64__) [[clang::optnone]] #endif void @@ -341,7 +341,7 @@ ecl_stack_frame_push_values(cl_object f) /* Some clang versions miscompile the following function on x86_64. * Temporarily turn off optimizations here. */ -#if defined(__clang__) && __clang_major__ >= 17 && __clang_major__ <= 19 && defined(__x86_64__) +#if defined(__clang__) && __clang_major__ >= 17 && __clang_major__ <= 22 && defined(__x86_64__) [[clang::optnone]] #endif cl_object From c12f8c2bc134d4e27255bf049e1fb9326577b7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Sun, 26 Apr 2026 10:27:13 +0200 Subject: [PATCH 3/8] symbols: add SI:*BREAK-LOCALS* to the list of symbols available in C --- src/c/symbols_list.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/c/symbols_list.h b/src/c/symbols_list.h index ff77ac41c..2a6992e8e 100644 --- a/src/c/symbols_list.h +++ b/src/c/symbols_list.h @@ -2043,6 +2043,7 @@ cl_symbols[] = { {EXT_ "ALLOW-WITH-INTERRUPTS" ECL_FUN(NULL, NULL, -1) ECL_VAR(MP_CONSTANT, OBJNULL)}, {SYS_ "*QUIT-TAG*" ECL_FUN(NULL, NULL, -1) ECL_VAR(SI_SPECIAL, OBJNULL)}, +{SYS_ "*BREAK-LOCALS*" ECL_FUN(NULL, NULL, -1) ECL_VAR(SI_SPECIAL, ECL_NIL)}, {EXT_ "ARRAY-RAW-DATA" ECL_FUN("si_array_raw_data", si_array_raw_data, 1) ECL_VAR(EXT_ORDINARY, OBJNULL)}, From dcc3a3c05a6143e7ec908f6686b387474f20a6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Sun, 26 Apr 2026 12:25:38 +0200 Subject: [PATCH 4/8] boot: allocate first_env dynamically at startup When mprotect is used as a cheap interrupt protection, the environment must be page-aligned. For static data we'd need to use a kludge (or alignas that is not part of C99) -- the simplest thing is to use the same mechanism to allocate the first environment as the rest. That will ensure page alignment when mprotect is used (that is, when mmap allocates the environment). This was not possible before (in !341), because back then, when mmap was not used, we've been using the garbage collector to allocate th environment, but now we use the manual allocator. Fixes #828. --- CHANGELOG | 7 +++++-- src/c/main.d | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 022b4e098..298581f1f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,8 +29,11 @@ * Pending changes since 26.3.27 -- bugfix: MAKE-PACKAGE destructively modified definning form conses of the - package local nicknames breaking bytecmp on such packages (#839) +- bugfix: MAKE-PACKAGE destructively modified defining form's cons cells of + the package local nicknames, breaking package literals in bytecmp (#839) + +- bugfix: the first environment is now always page-aligned by using the + same allocation mechanism as all subsequent envs (#828) * 26.3.27 changes since 24.5.10 diff --git a/src/c/main.d b/src/c/main.d index 7f06fe6a7..f00464c1e 100644 --- a/src/c/main.d +++ b/src/c/main.d @@ -49,7 +49,6 @@ /******************************* EXPORTS ******************************/ const char *ecl_self; -static struct cl_env_struct first_env; /************************ GLOBAL INITIALIZATION ***********************/ @@ -419,7 +418,7 @@ struct cl_core_struct cl_core = { .system_properties = ECL_NIL, - .first_env = &first_env, + .first_env = NULL, #ifdef ECL_THREADS .processes = ECL_NIL, #endif @@ -498,6 +497,9 @@ cl_boot(int argc, char **argv) setbuf(stdin, stdin_buf); setbuf(stdout, stdout_buf); #endif + + /* The first environment must be available at all times. */ + cl_core.first_env = _ecl_alloc_env(NULL); init_process(); ARGC = argc; From d5a026e98a9716891f158c40fa4af893f2f5548e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Fri, 1 May 2026 23:07:09 +0200 Subject: [PATCH 5/8] si_load_bytecodes: use the same syntax for all bytecodes forms Before the last release we've introduced a new dispatch character macro #" that reads into base strings in the compiler environment, but si_load_bytecodes used it only for the first read form, something like: (let ((forms (with-ecl-syntax () (read-forms strm t)))) (loop for forms = forms then (read-forms strm nil) while forms do (process forms))) So if the file had more than one toplevel #Y, the reader broke on #"". Fixes #842. --- src/c/load.d | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/c/load.d b/src/c/load.d index 3862c9857..cca9bb54f 100644 --- a/src/c/load.d +++ b/src/c/load.d @@ -157,21 +157,22 @@ si_load_bytecodes(cl_object source, cl_object verbose, cl_object print, cl_objec cl_index bds_ndx = ecl_progv(env, ECL_CONS_CAR(progv_list), ECL_CONS_CDR(progv_list)); forms = read_forms(strm, ECL_T); - ecl_bds_unwind(env, bds_ndx); - } - while (!Null(forms)) { - if (ECL_LISTP(forms)) { - cl_object x = ECL_CONS_CAR(forms); - forms = ECL_CONS_CDR(forms); - if (ecl_t_of(x) == t_bytecodes) { - _ecl_funcall1(x); - if (Null(forms)) { - forms = read_forms(strm, ECL_NIL); + + while (!Null(forms)) { + if (ECL_LISTP(forms)) { + cl_object x = ECL_CONS_CAR(forms); + forms = ECL_CONS_CDR(forms); + if (ecl_t_of(x) == t_bytecodes) { + _ecl_funcall1(x); + if (Null(forms)) { + forms = read_forms(strm, ECL_NIL); + } + continue; } - continue; } + FEerror("Corrupt bytecodes file ~S", 1, source); } - FEerror("Corrupt bytecodes file ~S", 1, source); + ecl_bds_unwind(env, bds_ndx); } { cl_object x; From c9fd019adc4c2227e082d5956b5645dd341743c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Fri, 1 May 2026 23:14:33 +0200 Subject: [PATCH 6/8] news: update the changelog --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 298581f1f..82855af85 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -35,6 +35,8 @@ - bugfix: the first environment is now always page-aligned by using the same allocation mechanism as all subsequent envs (#828) +- bugfix: allow loading concatenated fasc files (#842) + * 26.3.27 changes since 24.5.10 - Vendored libffi has been updated to the version 3.5.2 From 9ec0bef93d4d26aeba0366e0636cfbf25fe34435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Mon, 4 May 2026 07:49:05 +0200 Subject: [PATCH 7/8] Update version number to 26.5.5. --- CHANGELOG | 4 +++- src/configure | 18 +++++++++--------- src/configure.ac | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 82855af85..b1afa1eb2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -27,7 +27,9 @@ install ECL on the preferred destination (specified with "--prefix" parameter given to configure script). -* Pending changes since 26.3.27 +* Pending changes since 26.5.5 + +* 26.5.5 changes since 26.3.27 - bugfix: MAKE-PACKAGE destructively modified defining form's cons cells of the package local nicknames, breaking package literals in bytecmp (#839) diff --git a/src/configure b/src/configure index dc0be976a..e197ef240 100755 --- a/src/configure +++ b/src/configure @@ -1,7 +1,7 @@ #! /bin/sh # From configure.ac Revision. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for ecl 26.3.27. +# Generated by GNU Autoconf 2.72 for ecl 26.5.5. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation, @@ -602,8 +602,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ecl' PACKAGE_TARNAME='ecl' -PACKAGE_VERSION='26.3.27' -PACKAGE_STRING='ecl 26.3.27' +PACKAGE_VERSION='26.5.5' +PACKAGE_STRING='ecl 26.5.5' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1404,7 +1404,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures ecl 26.3.27 to adapt to many kinds of systems. +'configure' configures ecl 26.5.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1474,7 +1474,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ecl 26.3.27:";; + short | recursive ) echo "Configuration of ecl 26.5.5:";; esac cat <<\_ACEOF @@ -1656,7 +1656,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ecl configure 26.3.27 +ecl configure 26.5.5 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -2258,7 +2258,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ecl $as_me 26.3.27, which was +It was created by ecl $as_me 26.5.5, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -12386,7 +12386,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ecl $as_me 26.3.27, which was +This file was extended by ecl $as_me 26.5.5, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12450,7 +12450,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -ecl config.status 26.3.27 +ecl config.status 26.5.5 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" diff --git a/src/configure.ac b/src/configure.ac index 5eff9a037..af6f149c7 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -8,7 +8,7 @@ dnl AUTOCONF configuration for ECL dnl Giuseppe Attardi 25.1.1994 dnl -AC_INIT([ecl],[26.3.27],[]) +AC_INIT([ecl],[26.5.5],[]) AC_REVISION([$Revision$]) AC_CONFIG_SRCDIR([bare.lsp.in]) AC_CONFIG_AUX_DIR([gmp]) From 20d92666642472bd04c22eccdd7b64c67373f957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Tue, 5 May 2026 11:00:38 +0200 Subject: [PATCH 8/8] proclaim-class: use the correct env and don't redefine in bytecmp PROCLAIM-CLASS in ccmp had the following form in its body: (ext:with-backend :c/c++ (register-in-ccmp) :bytecmp (register-globally)) with a clear intention, that CCMP-compiled code should use the first path, and BCMP-compiled code should use the second. But that's not what this operator does. This operator caused, that when CCMP was compiled with CCMP, then it always took (register-in-ccmp) path (even for bytecodes compiler(!)), while when CCMP was compiled with BCMP (i.e with a flag --disable-shared and compiler is not builtin), then modifying global instance was always called, disregrading whether we were compiling with CCMP or BCMP at the moment. We've replaced this with a more precise statement that decides at runtime which compiler to chose: (if *compiler-in-use* (register-in-ccmp) (register-globally)) The other part of the problem was that registering the class definition globally in the bytecodes compiler (or in ccmp when --disable-shared was true), could redefine existing class in runtime environment with a forward-referenced-class, and that lead to the environment corruption. Consider: (compile-file "foo.lisp" :load t) ;defines globally at load time "#" (compile-file "foo.lisp" :load nil) ;defines globally at compile time "#" So after compiling the second file, we don't have the standard class foo, that we may depend on in later files. Fixes #843. --- CHANGELOG | 3 +++ src/cmp/cmpenv-proclaim.lsp | 9 ++++++--- src/lsp/predlib.lsp | 9 ++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b1afa1eb2..9394a870f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -39,6 +39,9 @@ - bugfix: allow loading concatenated fasc files (#842) +- bugfix: defclass does not redefine existing classes at compile time with + forward-referenced classes (#843) + * 26.3.27 changes since 24.5.10 - Vendored libffi has been updated to the version 3.5.2 diff --git a/src/cmp/cmpenv-proclaim.lsp b/src/cmp/cmpenv-proclaim.lsp index 6394b4502..9bdd63b19 100644 --- a/src/cmp/cmpenv-proclaim.lsp +++ b/src/cmp/cmpenv-proclaim.lsp @@ -121,9 +121,12 @@ (si:put-sysprop var 'CMP-TYPE type1)) (warn "The variable name ~s is not a symbol." var)))) +;;; FIXME implement file-local global compiler environment for BCMP compiler and +;;; unify compiler environment functions with CCMP. (defun si:proclaim-class (name class &optional (env c::*cmp-env-root*)) "Add a class definition to the global compiler environment." (si:create-type-name name) - (ext:with-backend - :c/c++ (cmp-env-register-type name class c::*cmp-env-root*) - #-ecl-min :bytecodes #-ecl-min (setf (find-class name) class))) + (if *compiler-in-use* + (cmp-env-register-type name class c::*cmp-env-root*) + (or (find-class name nil) + (setf (find-class name) class)))) diff --git a/src/lsp/predlib.lsp b/src/lsp/predlib.lsp index ac2b2c550..36226eb17 100644 --- a/src/lsp/predlib.lsp +++ b/src/lsp/predlib.lsp @@ -36,13 +36,16 @@ Builds a new function which accepts any number of arguments but always outputs N (ext:fill-array-with-elt *subtypep-cache* nil 0 nil) (ext:fill-array-with-elt *upgraded-array-element-type-cache* nil 0 nil)) +;;; FIXME implement file-local global compiler environment for BCMP compiler and +;;; unify compiler environment functions with CCMP. (defun proclaim-class (name class &optional env) "Add a class definition to the global compiler environment." (declare (ignore env)) - ;; Default implementation for the bytecodes compiler which doesn't - ;; have a separate file-local compiler environment. + ;; Default implementation for the bytecodes compiler which doesn't have a + ;; separate file-local compiler environment. (si:create-type-name name) - (setf (find-class name) class)) + (or (find-class name nil) + (setf (find-class name) class))) (defun create-type-name (name) (when (member name *alien-declarations*)