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. # 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.