From 70b58fd80f37813e3a8ff01db61a82821a14d020 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 13 Nov 2026 13:36:38 +0900 Subject: [PATCH 1/2] 0.20.2: i686 --- the x87 routines kept, atomic.c for sixty-four bit atomics on four-aligned objects --- README.md | 18 +++++++++++++++++- mcpp.toml | 19 ++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 95b3cf18..76432b12 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ C library. ```toml [dependencies] -openkal-llvm-runtime = "0.20.1" +openkal-llvm-runtime = "0.20.2" ``` > **Engine floor (mcpp 2026.11.2.1):** 0.17.0 is built over openkal-musl 0.26.0, @@ -328,6 +328,22 @@ openkal-musl 0.27.3 selects openkal-linux 0.24.1 on Linux and openkal-ld 0.4.3 for an image. Linux confinement requires Landlock ABI 3 to enforce read-only grants against raw file truncation. The runtime implementation is unchanged. +## i686 (0.20.2) + +Built for `i686-linux-musl` above openkal-musl and openkal-linux on i386 +(openkal 0.25.1, clause 5.5), the selection of compiler-rt differs from the +sixty-four bit one in two files. The x87 routines (`*xf*.c`, `*xc3.c`, the 80-bit +`long double`) are kept, as on x86_64: the type is real on i386 too. And +`atomic.c` is compiled: a sixty-four bit atomic on an object the compiler cannot +prove eight-byte aligned --- an `int64_t` field of a structure, which i386 aligns +to four --- is the call `__atomic_load` rather than an instruction, and the +embedded allocator's statistics make such loads (measured: `undefined symbol: +__atomic_load`). It takes its own locks and calls nothing of the system. Measured +locally above the family's i386 branches: a C++23 program with `import std`, an +exception, four `std::jthread`s, `std::format` of sixty-four bit values and a +file stream ran, and the openkal conformance suite held every observation it +made (407, none did not, the five not observed being x86_64's five). + ## OpenKal 0.25 dependency group Runtime 0.20.1 builds for FreeBSD above openkal-musl (`x86_64-freebsd-musl`, diff --git a/mcpp.toml b/mcpp.toml index 18d178ad..1f5d52b5 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-llvm-runtime" -version = "0.20.1" +version = "0.20.2" description = "LLVM's C++ runtime libraries — libc++, libc++abi and libunwind — configured for openkal-musl rather than for a host C library." license = "Apache-2.0" authors = ["mcpplibs"] @@ -496,7 +496,7 @@ sources = [ [target.'cfg(any(os = "linux", os = "openkal"))'.build] sources = [ "llvm/compiler-rt/lib/builtins/*.c", - "!llvm/compiler-rt/lib/builtins/atomic*.c", + "!llvm/compiler-rt/lib/builtins/atomic_*.c", "!llvm/compiler-rt/lib/builtins/clear_cache.c", "!llvm/compiler-rt/lib/builtins/emutls.c", "!llvm/compiler-rt/lib/builtins/enable_execute_stack.c", @@ -550,12 +550,25 @@ sources = [ # today, so the exclusion looked like an OS property. It is not. Sorting on the # axis the fact actually lives on is what makes a second architecture work # without a third copy of the list. -[target.'cfg(all(any(os = "linux", os = "openkal", os = "freebsd"), not(arch = "x86_64")))'.build] +[target.'cfg(all(any(os = "linux", os = "openkal", os = "freebsd"), not(arch = "x86_64"), not(arch = "i686")))'.build] sources = [ "!llvm/compiler-rt/lib/builtins/*xf*.c", "!llvm/compiler-rt/lib/builtins/*xc3.c", ] +# THE GENERIC ATOMICS ARE A THIRTY-TWO BIT WORD'S (i686; openkal 0.25.1, clause +# 5.5). A sixty-four bit atomic on an object the compiler cannot prove eight-byte +# aligned --- an `int64_t` field of a structure, which i386 aligns to four --- is +# the call `__atomic_load' rather than an instruction; the embedded allocator's +# statistics make such loads (measured: `undefined symbol: __atomic_load', +# i686-linux-musl). `atomic.c' answers them with its own locks and calls nothing +# of the system. Where the word is sixty-four bits nothing calls it, and it stays +# out, as before. +[target.'cfg(all(any(os = "linux", os = "openkal"), not(arch = "i686")))'.build] +sources = [ + "!llvm/compiler-rt/lib/builtins/atomic.c", +] + [target.'cfg(os = "openkal")'.build] # WHICH TARGET THIS IS, FOR THE ONE FILE THAT MUST KNOW IT IS AN OK IMAGE. # From 50da05d55a81829c572a652ca2593d2b71840d10 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 13 Nov 2026 14:08:25 +0900 Subject: [PATCH 2/2] branch graph: a backend's tree within the range the C library states Without a branch of the same name a backend's default branch was taken. openkal- windows main is on 0.22 while openkal-musl names ^0.21.1 and mcpplibs.os bounds it below 0.22, so the Windows host's graph was refused. The default branch is taken when its version is within the stated range, and otherwise the newest release within it. --- tools/branch-graph.sh | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/tools/branch-graph.sh b/tools/branch-graph.sh index 45e2e1fe..9df98b09 100755 --- a/tools/branch-graph.sh +++ b/tools/branch-graph.sh @@ -39,19 +39,47 @@ branch="${1:-}" root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$root" +# Whether VERSION satisfies a caret RANGE (^a.b.c: below 1, the same minor +# version; from 1, the same major version; never below a.b.c). +in_range() { + local version="$1" floor="${2#^}" + local vM vm vp fM fm fp + IFS=. read -r vM vm vp <<< "$version" + IFS=. read -r fM fm fp <<< "$floor" + [ "$vM" = "$fM" ] || return 1 + if [ "$fM" = 0 ]; then [ "$vm" = "$fm" ] && [ "$vp" -ge "$fp" ]; return; fi + [ "$vm" -gt "$fm" ] || { [ "$vm" = "$fm" ] && [ "$vp" -ge "$fp" ]; } +} + # Clones a repository of this ecosystem, preferring the branch under test when -# that repository has one of the same name. +# that repository has one of the same name. Without one, the default branch is +# taken if its version is within RANGE, the range the C library states for it; +# a default branch that has moved to a later line than the family's (openkal- +# windows 0.22 while the family names ^0.21.1, and mcpplibs.os bounds it below +# 0.22) is replaced by the newest release within the range, so the graph is one +# the resolver accepts. fetch() { - local repo="$1" dir="$2" + local repo="$1" dir="$2" range="${3:-}" rm -rf "$dir" git clone --quiet "https://github.com/mcpplibs/$repo.git" "$dir" if git -C "$dir" rev-parse --verify --quiet "origin/$branch" > /dev/null; then git -C "$dir" checkout --quiet "origin/$branch" printf ' %-22s %s %s\n' "$repo" "$branch" "$(git -C "$dir" rev-parse --short HEAD)" - else + return + fi + local version + version="$(sed -n 's/^version[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p' "$dir/mcpp.toml" | head -1)" + if [ -z "$range" ] || in_range "$version" "$range"; then printf ' %-22s default branch %s (it has no %s)\n' \ "$repo" "$(git -C "$dir" rev-parse --short HEAD)" "$branch" + return fi + local tag + tag="$(git -C "$dir" tag --sort=-v:refname | while read -r t; do + in_range "${t#v}" "$range" && { echo "$t"; break; }; done)" + [ -n "$tag" ] || { echo "::error::$repo has no release within $range (its default branch is $version)"; exit 1; } + git -C "$dir" checkout --quiet "$tag" + printf ' %-22s release %s, within %s (its default branch is %s)\n' "$repo" "$tag" "$range" "$version" } # In-place editing that both GNU and BSD sed perform identically. @@ -80,7 +108,8 @@ manifests=(mcpp.toml .musl/mcpp.toml) # The first was fixed by naming it, and the second appeared. A list written by # hand is a list that is one entry short, so the set is read out of the manifest. for backend in $(grep -oE '^openkal-[a-z]+ = \{ version' .musl/mcpp.toml | cut -d' ' -f1); do - fetch "$backend" ".$backend" + range="$(sed -n "s/^$backend = { version = \"\([^\"]*\)\".*/\1/p" .musl/mcpp.toml | head -1)" + fetch "$backend" ".$backend" "$range" # The backend reaches the specification too, by whatever form its own # manifest uses. From /./ the specification is ../.spec.