Skip to content

What stops LLVM building for a ToyOS host, ordered by what blocks what: M2's clang and lld first, then M3's rustc - #644

Merged
Japabu merged 5 commits into
mainfrom
wt/toyos-rustcllvm
Sep 30, 2026
Merged

Japabu merged 5 commits into
mainfrom
wt/toyos-rustcllvm

Conversation

@Japabu

@Japabu Japabu commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

The self-hosting scout's findings: what stops LLVM building for a ToyOS host, ordered by what blocks what and filed under the milestone each blocks, each with an exit a build or a test can fail. Issues only. No fork is touched, and no code.

The order

issues/build/toyos-builds-itself.md closes with the two lists.

M2, LLVM, clang and lld built for a ToyOS host:

  1. Configure: bootstrap-cannot-build-llvm-clang-and-lld-for-a-toyos-host.md's clang-tblgen and CMake system, and the-c-sysroot-has-no-libm-so-llvms-configure-fails.md.
  2. Compile: toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md, the names it leaves to the header-drift issue, and the bootstrap issue's bit.h and is_local_impl.
  3. Link: the POSIX issue's functions, stage 3 of the child-process track, and libc-has-no-alarm.md.
  4. Run: the issues for mmap, fcntl/chmod/fchmod, pread/pwrite and readdir.

M3, a rustc that carries that LLVM, after all of M2's:

  1. Build: rustc-llvm-cannot-build-for-a-toyos-host.md.
  2. Link: a-rust-std-binary-cannot-link-the-cxx-runtime.md (on main, from A C++ runtime for ToyOS: libc++, libc++abi and libunwind in every C sysroot #637) and a-rust-std-program-defines-no-aligned-alloc.md.
  3. Test: a-worktree-cannot-build-a-hosted-rustc-of-its-own.md.
  4. The linker: the-hosted-rustc-names-a-linker-toyos-does-not-have.md. toyos-ld is not that linker: it refuses every executable with thread-local storage (ld/toyosld.log).

Decisions

  • Bootstrap's LLVM and rustc_llvm are two issues. Bootstrap reads CLANG_TABLEGEN only when it builds clang (src/bootstrap/src/core/build_steps/llvm.rs, builder.config.llvm_clang), so clang-tblgen, the CMake system, bit.h and is_local_impl block M2, whose exit is bootstrap, with clang = true, installing a clang and an ld.lld for x86_64-unknown-toyos. rustc_llvm blocks M3 alone and keeps the exit the guest's rustc -vV printing LLVM version:; today's hosted rustc fails it, because Cranelift's print_version prints Cranelift version:.
  • No ToyOS tool changes LLVM or Rust. bit.h, is_local_impl, bootstrap's CMake system and rustc_llvm's C++ runtime and C library are ToyOS platform arms at existing dispatch sites. clang-tblgen and rustc_llvm's cross paths are none: each names what ToyOS's own build must do. Bootstrap finds clang-tblgen only in the CMake build directory of a host LLVM it built itself, and rustc_llvm finds a cross target's LLVM by swapping the host triple in the host LLVM's paths. Both hold for a bootstrap build directory that holds both LLVMs, and neither holds for the store's, which every compiler build names as the host's llvm-config.
  • Bootstrap's arm needs CMake to know ToyOS. LLVM's configure answers CMAKE_SYSTEM_NAME=ToyOS without UNIX with Unable to determine platform (HandleLLVMOptions.cmake at 849da7d62). CMake sets UNIX only from a platform module (Platform/UnixPaths.cmake), so the bootstrap issue cites the-cxx-runtime-names-toyos-to-cmake-as-unix.md.
  • aligned_alloc's exit asks for the alignment and the layout. The address must be a multiple of the requested alignment, asserted at 64 and 4096. free and realloc must release each block at the layout it was allocated with, which no case can see: std's dlmalloc 0.2.14 checks a freed block's size (validate_size) and ignores its alignment. realloc is in the exit beside free because it releases the old block at alignment 16 today, as free does.
  • Every libc case reads its effect back. fcntl's case asserts F_GETFL on an O_RDWR | O_APPEND descriptor and F_DUPFD answering at least its argument, and chmod (setPermissions in Unix/Path.inc calls it beside fchmod) joins fchmod. The POSIX case reads back the old mask a second pthread_sigmask or sigprocmask answers, getrlimit after setrlimit, readlink of symlink, and the file through link's name; sigprocmask, which answers 0 and does nothing and which LLVM calls (Unix/Signals.inc), is on the issue. SIGUSR1 is on its signal.h line: the header-drift issue's exit checks prototypes only. alarm(0) answers 1 to 5 after alarm(5), and 0 again after that, because LLVM's Wait disarms with alarm(0) before restoring the old SIGALRM action. pread's race case runs over a file whose every 8-byte word holds its own offset, with today's pread and pwrite as its negative control. readdir's case asserts a directory never answers DT_REG.
  • mmap's exit is the refusal, ENODEV for a file mapping, shared or private, at offset 0 or a later page. The kernel maps no file, and LLVM falls back when a map fails: to read in MemoryBuffer, to a buffer in memory in FileOutputBuffer. FileOutputBuffer maps lld's output shared and writable, which libc maps private today, so lld in the guest would write zeros and report success. That is read from FileOutputBuffer.cpp, not run.

Evidence

Logs under the job's scratchpad, orch/rustcllvm/. They back the 20 failed objects, 12 of them in rustc's 71 libraries (build-libs.log, NINJA_EXIT=1), down to none (build-libs3.log, NINJA_EXIT=0). They back the 17 duplicates (link-shared2.log, LINK_EXIT=1), the two TPOFF32 errors and the 36 undefined symbols (link-shared3.log, LINK_EXIT=1), and the toyos-ld refusal (ld/toyosld.log).

The configure ran on git archive of llvm/, cmake/ and third-party/ at 849da7d62 into scratch, so the fork clone was untouched. The C sysroot was an APFS clone of #637's de0de8ee7862147a c/, built with that sysroot's clang and with llvm-tblgen from store LLVM 1425e623e612b348. No scratch headers were used.

  • As laid out: CONFIGURE_EXIT=1 at CheckAtomic.cmake:59 (r2/configure-red.log). The log holds unable to find library -lm 18 times, and -lpthread, -lc, -ldl, -lrt and -latomic once each.
  • With empty libm.a, libpthread.a, libdl.a and librt.a: CONFIGURE_EXIT=0 (r2/configure-green.log). Eleven probes flip from failed to passed (r2/probes-red.txt against r2/probes-green.txt).

The bootstrap and rustc_llvm findings are read, not run: llvm.rs and rustc_llvm/build.rs at the fork pin aca5f527f, and HandleLLVMOptions.cmake, bit.h, Unix/Path.inc, Unix/Program.inc, Unix/Process.inc, Unix/Signals.inc and CrashRecoveryContext.cpp fetched from ToyOSOrg/llvm-project at 849da7d62.

Gates, at this branch's head

  • cargo run -- --ci host at 94139d9e4: EXIT=0, "56 step(s), all green" (r3/ci-host2.log).

No guest run is needed: the branch changes issues/ only.

Unsure

  • The POSIX list comes from scratch declarations whose types and values were stand-ins. A correct declaration may surface a name the list lacks. The bootstrap issue's exit, clang and lld built for ToyOS, is what finds it.
  • Eight objects outside rustc's 71 libraries failed and were not chased, and clang's and lld's own libraries were never built. So what M2 needs beyond this list is unmeasured, and the POSIX issue says so.
  • The C-side measurements are on A C++ runtime for ToyOS: libc++, libc++abi and libunwind in every C sysroot #637's sysroot de0de8ee7862147a, built from its branch, and none was repeated on a sysroot built from main.
  • ENODEV is the errno POSIX gives for a file mmap cannot map. Refusing, rather than copying the file into private memory as the memmap2 fork does for read-only mappings, is a choice between two exits that both hold.
  • The alarm(0) answers show what libc records, not that no timer is left armed; no case here can show that without waiting on a signal that should never come.
  • Both remedies that keep bootstrap and LLVM unchanged ask src/llvm.rs's store to change how it builds or lays out an LLVM. Neither is designed here.

🤖 Generated with Claude Code

https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L

The scout for M3's rustc half of issues/build/toyos-builds-itself.md. Nothing
but issues/ changes: the first blocker is outside this brief (the C library),
and the exit is further blocked on M2's LLD and on the tooling.

How each number was taken, at main 649ea51, with #637's C sysroot
de0de8ee7862147a (libc++ in it, clang and LLVM at 849da7d62), APFS-cloned into
scratch so nothing of another worktree's was written:

- LLVM for a ToyOS host. CMake cross-configure of src/llvm-project/llvm
  (849da7d62, a private detached worktree of the fork clone) with that clone's
  clang for x86_64-unknown-toyos, CMAKE_SYSTEM_NAME=ToyOS and UNIX=ON as
  src/libcxx.rs names the system, the store LLVM's llvm-tblgen, targets
  AArch64;X86 as clang::LLVM_CONFIG, every host library off. Configure exit 1
  at CheckAtomic.cmake:59 with 18 "unable to find library -lm"; with empty
  libm/libpthread/libdl/librt archives in the scratch sysroot, exit 0.
- `ninja -k 0 llvm-libraries`, with only a scratch machine/endian.h: 20 objects
  failed, 12 of them in the 71 libraries rustc links (llvm-config --libnames of
  rustc_llvm's required components plus x86 and aarch64): 9 in LLVMSupport,
  Host.cpp in LLVMTargetParser, two MachO files in LLVMObjectYAML. Scratch
  headers and forced declarations were added for each missing name, in three
  layers, until `ninja -k 0` of those 71 targets exited 0. The issue lists
  every name a layer added.
- The link. compiler/rustc_llvm/llvm-wrapper from the pinned fork, compiled for
  the target with the same defines rustc_llvm's build script gives, archived
  and linked --whole-archive with the 71 archives, libc++.a and the Rust
  sysroot's archives (libtoyos_c.a among them) by ld.lld -shared -z defs:
  17 duplicate _Unwind_* (libc++.a's libunwind against std's `unwinding`),
  2 R_X86_64_TPOFF32 "cannot be used with -shared" against libc++abi's
  eh_globals; with --allow-multiple-definition, 36 undefined symbols, 29 of
  them C functions (the other 7: std's allocator shim, LLVMRustStringWriteImpl,
  main). With --noinhibit-exec -z undefs it wrote a 55,071,992-byte object,
  41,131,639 bytes of text.
- The linker. A host build of toyos-ld (cargo build -p toyos-ld --release)
  as -C linker for a std hello.rs compiled for x86_64-unknown-toyos: exit 1,
  "an executable with thread-local storage: toyos-ld is frozen"; through
  rust-lld, exit 0.

What is read from code and not run is said so in the track: bootstrap's
Generic fallback for CMAKE_SYSTEM_NAME, its clang-tblgen panic with an
external host LLVM, rustc_llvm's stdc++/C-library/triple-replacement arms,
and the two LLVM sites with no ToyOS arm. libc's mmap dropping fd and offset
is read from userland/libc/src/posix_io.rs.

Filed: the track and five issues it points at. toyos-builds-itself.md gains
one pointer paragraph at its end, clear of the lines #637 rewrites.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
@Japabu
Japabu marked this pull request as ready for review September 30, 2026 21:29
@Japabu

Japabu commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator Author

Round 1 at e32875322. CI host SUCCESS at this head (run 36779786970, job 110106789860). The branch adds no tests and targets no hardware. Net +195 −0, all of it prose under issues/: production 0, tests 0.

BLOCKER

  • issues/build/the-hosted-rustc-carries-cranelift-because-llvm-does-not-build-for-toyos.md:11 — the exit, "a Rust program compiled and run inside ToyOS by that rustc", is word for word M3's rustc exit (toyos-builds-itself.md:31-32) and is the exit of the-hosted-rustc-names-a-linker-toyos-does-not-have.md:17-18. The Cranelift rustc write_config builds today (src/toolchain.rs:839-851) meets it on the day a linker runs in the guest — why: the track is a second record of M3's rustc half, and its exit cannot fail on its own title. Delete the track. Point M3 at the five issues in toyos-builds-itself.md. Put the four "What the build must also do" items into one issue whose exit a build can fail, e.g. bootstrap builds rustc_llvm for x86_64-unknown-toyos and the guest's rustc -vV prints LLVM version:.
  • the-hosted-rustc-carries-cranelift-...md:14-30, toyos-builds-itself.md:65-66 — the track is not ordered by what blocks what. The libm, POSIX-surface and mmap issues, and the bit.h/Path.inc arms (track:50-51), stop LLVM building for a ToyOS host at all. That makes them blockers of M2's clang and lld first (toyos-builds-itself.md:23-28, whose own line 47 already asks for "mmap mature enough for LLVM"), and of toyos-has-no-c-compiler-inside-it.md's exit, before they block M3's rustc — why: filed under "M3's rustc half" alone, they are invisible to whoever works M2. The order is: configure (libm; bootstrap's Generic, track:37-41), then compile (POSIX surface, bit.h, Path.inc), then link (the 29 functions; the unwinder and TPOFF32, which alone are M3's), then run (mmap), then test (worktree), then the exit (linker). The track lists the C++ runtime first.
  • issues/build/toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md:19,24-26,30,40-43 — this duplicates two issues the tree already has. Stage 3 of issues/kernel/a-childs-end-is-an-event-and-a-parent-takes-its-children-down.md:76-77 owns wait, wait4, "the signal-set calls" (sigemptyset, sigfillset, sigaddset) and starting a child process, under owner rulings. posix_spawn is that start, and LLVM falls back to its execv/execve path only when posix_spawn is missing. libc-headers-are-written-by-hand-and-drift-from-its-definitions.md:25,34 owns SIGUSR1 and "a definition a header was meant to declare and does not", which is the dirent.h of line 19 — why: this issue's exit, "leaves no C function undefined", can be met by a second implementation that lands ahead of stage 3. Cite both and take those names out of this exit.
  • toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md:47-49 — the exit checks only declarations and a link, so stubs pass it. Declare struct flock/F_SETLK (line 33), and LLVM's sys::fs::tryLockFile calls libc's fcntl, which answers 0 to every command (userland/libc/src/posix_io.rs:368-371). LLVM then believes it holds a file lock nobody holds, and the exit passes. The same goes for an alarm that returns 0 and arms nothing — why: the exit admits a silent failure. It must require each name to do what POSIX says or refuse with errno set, with ENOSYS where ToyOS rules the call out (setsid, execv), and a case per refusal. The fcntl stub is untracked and needs a defect of its own, cited here.

NOTE

  • issues/build/the-c-sysroot-has-no-libm-so-llvms-configure-fails.md:22-23 — the libm fix alone cannot meet "finds every function libtoyos_c.a defines". pread is defined (posix_io.rs:375) and declared by no header, and the green arm's own log reads Looking for pread - not found (configure-llvm.log:200). That gap is the header-drift issue's. Once pread is found, LLVM uses libc's seek-read-seek pread (posix_io.rs:373-381), which races any thread sharing the descriptor. File that race, and cut the exit's second clause to the probes this issue fails.
  • issues/build/libc-mmap-ignores-the-file-it-is-asked-to-map.md:16-18 — the two halves of the exit disagree. A refusing mmap satisfies "or fails with errno set" but fails "maps a file ... and reads its bytes back", and MemoryBuffer falls back to read when a map fails, so a refusal is a legitimate fix. Pick one. The guest case maps at offset 0, so a fix that ignores offset passes: map at a non-zero page offset. MAP_SHARED is dropped to PRIVATE (posix_io.rs:514), so writes through a writable shared file mapping vanish. That belongs in this exit or in an issue of its own.
  • toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md:21,48 — the scratch headers supplied machine/endian.h, which is what bit.h:53 includes on ToyOS, and no endian.h. Path.inc:568's fallback reads MNT_LOCAL, which the scratch sys/statvfs.h defined. So "nothing declared beside it" needs either the track's two LLVM arms or libc carrying BSD names to avoid them. The issue should say which; the owner's rule prefers the upstream-shaped arms.
  • the-c-sysroot-has-no-libm-...md:22, toyos-libc-lacks-...md:47 — both exits are one-off agent runs that no gate repeats. After the issue closes, a libc edit can break them again silently until M2 builds LLVM for ToyOS. Name a host test: clang compiles and links one probe per name against the C sysroot.
  • issues/build/a-rust-std-binary-cannot-link-the-cxx-runtime.md:10-23 and the three C-side issues — they measure A C++ runtime for ToyOS: libc++, libc++abi and libunwind in every C sysroot #637's sysroot, whose libc differs from main's in 58 files (aligned_alloc and strerror_r exist only there). Land this after A C++ runtime for ToyOS: libc++, libc++abi and libunwind in every C sysroot #637. The two-unwinder and TPOFF32 defect is in A C++ runtime for ToyOS: libc++, libc++abi and libunwind in every C sysroot #637's artifact, so route it to A C++ runtime for ToyOS: libc++, libc++abi and libunwind in every C sysroot #637's review.
  • issues/build/a-worktree-cannot-build-a-hosted-rustc-of-its-own.md:22-24 — The toolchain is a content-addressed store built in one shared fork checkout; buildlock, keystore, worktree and identity go #629 (open) deletes the hosted rustc's build, Owner, the compiler record and --worktree, and files the-hosted-rustc-is-not-built.md. Its exit, a store product keyed on a compiler builds the hosted rustc and an image carries it, covers this one. Whichever of the two lands second folds this issue into it.
  • Evidence. Backed by a log: the 17 duplicates (link-shared2.log, LINK_EXIT=1); the 2 TPOFF32 errors and 36 undefined symbols (link-shared3.log, LINK_EXIT=1); the 20 failed objects, 12 of them in the 71 libraries (build-libs.log, NINJA_EXIT=1), down to none (build-libs3.log, NINJA_EXIT=0); configure exit 0 (configure-llvm.log); the toyos-ld refusal (ld/toyosld.log). No log: the configure exit-1 arm (both configure logs end CONFIGURE_EXIT=0), the rust-lld control (ld/lld.log is empty and records no exit code), and the 55,071,992 and 41,131,639 byte sizes. The sites the track says were read and not run check out: bootstrap llvm.rs:534-539,731,738, rustc_llvm/build.rs:459-461,493-508, HandleLLVMOptions.cmake:245-246, config-ix.cmake:60-62, kernel/src/syscall/vm.rs:34.
  • Owner's rule — nothing changes LLVM or Rust beyond a platform arm. The one risk is track:42-45 (clang-tblgen). The likely fix, taking it from beside an external llvm-config, changes cross-platform bootstrap behaviour, the same shape lld-beside-an-external-llvm-config-is-carried-without-an-upstream-pr.md already carries. Say that it is fixed in ToyOS's build or written as upstream would take it.
  • issues: C and C++ conformance is upstream's own suites, judged by their own oracles #605 (open) — libc-test's API tests will fail on the same missing headers. This is overlap, not duplication: when issues: C and C++ conformance is upstream's own suites, judged by their own oracles #605 lands, its failing rows cite the POSIX issue.

REMOVE

  • the-hosted-rustc-carries-cranelift-...md:14 — "each measured against main 649ea51d4": the libc and libc++ measured are A C++ runtime for ToyOS: libc++, libc++abi and libunwind in every C sysroot #637's.
  • the-hosted-rustc-carries-cranelift-...md:33-34 — the 41,131,639 bytes of text: no log, measured on a link forced through duplicate and undefined symbols, and nothing reads the number.
  • the-hosted-rustc-carries-cranelift-...md:22-26 — "hello.rs, compiled ... through rust-lld, exit 0." narrates a refusal toyos-ld makes by design (toyos-ld/src/lib.rs:44); the clause before it already carries the fact.
  • a-rust-std-binary-cannot-link-the-cxx-runtime.md:19-20 — "at libunwind's UnwindLevel1.c and at unwinding's src/unwinder/mod.rs:346": a line citation into a third-party crate, which will rot.

SEND BACK

Japabu added a commit that referenced this pull request Sep 30, 2026
The track loses M3's C++ runtime clause here, and the runtime cannot yet
link into a Rust std binary: two unwinders and local-exec thread-locals.
That record reaches main with this branch, byte for byte as #644 wrote it
at e328753; every citation it makes resolves here.

n2's doc drops "one commit, with its own lock": `--rev` and `--locked`
say it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…s a build or a test can fail

Round 2 of the scout, answering the review of e328753.

The track goes. Its exit was M3's rustc exit word for word, which the Cranelift
rustc meets the day a linker runs in the guest, so it could not fail on its own
title. toyos-builds-itself.md now orders what stops LLVM building for a ToyOS
host, configure, compile, link, run, test, then the linker, and says which of
it blocks M2's clang and lld before M3's rustc; toyos-has-no-c-compiler-inside-it.md
cites the same issues. Both edits sit clear of the lines #637 and #568 rewrite.

The track's "what the build must also do" becomes
llvm-and-rustcs-build-have-no-arm-for-a-toyos-host.md, whose exit is
bootstrap building rustc_llvm for x86_64-unknown-toyos and the guest's
`rustc -vV` printing `LLVM version:`: the Cranelift backend's print_version
prints `Cranelift version:` (rust/compiler/rustc_codegen_cranelift/src/lib.rs),
so today's hosted rustc fails it. The bit.h and Path.inc fixes are said to be
upstream-shaped LLVM arms, and clang-tblgen and the cross target's paths to be
fixed in ToyOS's build or carried as the LLD precedent is.

The POSIX-surface issue gives stage 3 of the child-process track wait, wait4
and the signal-set calls, and the header-drift issue SIGUSR1 and the names libc
defines and declares nowhere (dirent.h, ftruncate, fchmod). Its exit now asks
each name to do what POSIX says or refuse as POSIX reports an error, ENOSYS
for setsid, getsid, execv and execve, with a guest C case per function and a
host test that compiles and links one probe per name against the C sysroot.
alarm leaves it for libc-has-no-alarm.md: POSIX gives alarm no refusal, and its
SIGALRM reaches a handler only through stage 3's imitated signals.
aligned_alloc leaves it for a-rust-std-program-defines-no-aligned-alloc.md:
link-shared3.log has libc++.a's stdlib_new_delete.cpp and fallback_malloc.cpp
reference it, and in a std program the C allocator is std's
(rust/library/std/src/sys/pal/toyos/mod.rs), not libc's.

Filed: fcntl's and fchmod's answer-0 stubs; pread and pwrite's seek-read-seek,
which LLVM reads every file slice through once a header declares pread; and
readdir answering DT_REG for a directory, which LLVM trusts once dirent.h
defines DTTOIF.

mmap's exit is the refusal: a file mapping, shared or private, answers ENODEV.
The kernel maps no file, and LLVM falls back to read (MemoryBuffer) and to a
buffer in memory (FileOutputBuffer) when a map fails. The shared case is in
that exit: FileOutputBuffer maps lld's output MAP_SHARED and writable, which
libc maps private, so lld inside ToyOS would write zeros and report success.
Read from llvm/lib/Support/FileOutputBuffer.cpp at 849da7d62, not run.

The configure's exit-1 arm now has a log. Rerun at 849da7d62 (git archive of
llvm/, cmake/, third-party/ into scratch) against APFS clones of #637's C
sysroot de0de8ee7862147a's c/, with the sysroot's own clang and the store
LLVM 1425e623e612b348's llvm-tblgen, no scratch headers:
- as laid out: CONFIGURE_EXIT=1 at CheckAtomic.cmake:59; CMakeConfigureLog.yaml
  holds `unable to find library -lm` 18 times and -lpthread, -lc, -ldl, -lrt
  and -latomic once each;
- with empty libm.a, libpthread.a, libdl.a and librt.a: CONFIGURE_EXIT=0; eleven
  probes flip from failed to passed between the two logs, and the libm exit
  names exactly those. pread is not found in either.
The rust-lld control and the byte sizes had no log and go with the track.

The worktree issue says #629's the-hosted-rustc-is-not-built.md covers it and
whichever lands second folds it. The C++ runtime issue loses the line
citations into libunwind and unwinding, and says #637's follow-up closes it;
#637 now carries a copy, and main's copy replaces this one once #637 lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
@Japabu Japabu changed the title The hosted rustc cannot carry LLVM yet: what stops it, measured What stops LLVM building for a ToyOS host, ordered by what blocks what: M2's clang and lld first, then M3's rustc Sep 30, 2026
@Japabu

Japabu commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator Author

Round 2 at a606e5d0d. CI host SUCCESS at this head (run 36783983873, job 110120851627). The branch adds no tests and targets no hardware. Net +378 −0, all prose under issues/: production 0, tests 0. Since round 1, main's merge excluded (12ce8f088..a606e5d0d): +281 −98.

Round-1 BLOCKERs

  • B1 CLOSED. The track is deleted (D in git diff --name-status 12ce8f088..HEAD). The build issue's exit fails today: the fork's Cranelift print_version prints Cranelift version: (rustc_codegen_cranelift/src/lib.rs:200-201 at c4c65e3e8), and the LLVM backend's prints LLVM version:.
  • B2 CLOSED. toyos-builds-itself.md:65-88 orders configure, compile, link, run, test, then the linker, with M2 first. The C++ runtime sits under link, as M3's alone. One item is on the wrong milestone: see the first BLOCKER.
  • B3 CLOSED. toyos-libc-lacks-...md:56-64 cites stage 3 and the header-drift issue. Stage 3 (a-childs-end-...md:71-77) names posix_spawn, waitpid, wait, wait4 and the signal-set calls. Those names are out of the exit.
  • B4 CLOSED. The exit (:66-73) asks for POSIX behaviour or POSIX's refusal, names ENOSYS for setsid, getsid, execv and execve, and requires a guest case per function and a host probe. The fcntl stub is its own defect, cited at :41-43. What the case asserts is a NOTE.

BLOCKER

  • issues/build/llvm-and-rustcs-build-have-no-arm-for-a-toyos-host.md:9-12,23-26,42-43, toyos-builds-itself.md:76-78 — "the last two are rustc's alone" contradicts the issue's own Build item — why: this branch exists to record the order, and the order puts an M2 blocker under M3. Bootstrap reads CLANG_TABLEGEN only when it builds clang (src/bootstrap/src/core/build_steps/llvm.rs:534-542, builder.config.llvm_clang). M2's clang for a ToyOS host is such a build; rustc_llvm is not. If M2 builds clang outside bootstrap, bootstrap's Generic is not M2's either. Whichever path M2 takes, one item is on the wrong milestone. The issue's one exit (rustc_llvm, and the guest's rustc -vV) is M3's, so the bit.h and is_local_impl arms it says block M2 cannot close when M2 lands. Split the issue. What bootstrap needs to build LLVM, clang and lld for x86_64-unknown-toyos gets an exit M2 can fail: bootstrap, with clang = true, installs a clang and an ld.lld for that host. rustc_llvm alone keeps rustc -vV.

  • issues/build/a-rust-std-program-defines-no-aligned-alloc.md:19-21 — the exit never asks for alignment — why: this is memory management, and the case cannot fail on the claim in the title. Two fixes pass it wrongly:

    • unsafe extern "C" fn aligned_alloc(_align: usize, size: usize) -> *mut u8 { malloc(size) }, added to std's c_allocator (library/std/src/sys/pal/toyos/mod.rs:111-170, whose malloc gives 16-aligned blocks), passes "allocates through aligned_alloc ... frees through free ... at an alignment above 16".
    • So does one that allocates Layout(HEADER + size, align) while free still deallocates at ALIGN 16 (:143-151), a layout mismatch the global allocator never reports.

    The exit requires the returned pointer to be a multiple of the requested alignment, which the guest case asserts at 64 and at 4096. It also requires free to release each block with the layout it was allocated at, the header carrying the alignment as A C++ runtime for ToyOS: libc++, libc++abi and libunwind in every C sysroot #637's libc backend's does.

NOTE

  • issues/build/libc-fcntl-and-fchmod-answer-0-and-do-nothing.md:9-13,20-24 — the exit leaves chmod silent. chmod (userland/libc/src/posix_io.rs:353, declared at include/sys/stat.h:63) is the same answer-0 stub, and LLVM's FilePermissionsApplier calls it (llvm/lib/Support/FileUtilities.cpp:322) beside fchmod (:324). Add it beside fchmod. Today's return 0 also passes an F_GETFL assert on an O_RDONLY descriptor, so the case asserts F_GETFL on one opened O_RDWR | O_APPEND, and asserts that F_DUPFD answers at least its argument.
  • toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md:71-73 — "asserts its answer" passes int pthread_sigmask(int h, const sigset_t *s, sigset_t *o) { return 0; }. Each case reads the effect back: the old set a second pthread_sigmask returns, getrlimit after setrlimit, readlink of what symlink made, and the file read through the name link made. sigprocmask (userland/libc/src/misc.rs:200) is the same stub, and no exit covers it.
  • toyos-libc-lacks-...md:60-62 — no exit covers SIGUSR1. The header-drift issue's exit checks function prototypes only (libc-headers-are-written-by-hand-...md:32-35). Round 1 sent it there, and round 1 was wrong. It goes back on this issue's signal.h line.
  • issues/build/libc-has-no-alarm.md:19-21 — no case asserts alarm(0). LLVM's Wait calls alarm(0) and then restores the old SIGALRM action (Program.inc:431-432,454-455). An alarm left armed later fires the default action and ends the process. An alarm(0) that answers the seconds left and disarms nothing passes this exit. The case asserts that after alarm(5), alarm(0) answers more than 0 and a second alarm(0) answers 0.
  • issues/build/libc-pread-and-pwrite-move-the-offset-another-thread-shares.md:20-22 — nothing says whether the race case can go red. The exit names today's pread as the negative control, measured red, over a file whose every 8-byte word holds its own offset.
  • issues/build/libc-readdir-calls-every-entry-a-regular-file.md:16-18 — the case only "reads", and a case that only reads passes today's DT_REG constant. It asserts the directory's entry answers DT_DIR or DT_UNKNOWN, never DT_REG.

REMOVE

SEND BACK

Japabu and others added 2 commits October 1, 2026 00:30
#637 carries issues/build/a-rust-std-binary-cannot-link-the-cxx-runtime.md;
main's copy is kept and this branch's is dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
…reads its effect back

The LLVM and rustc build issue is two. Bootstrap reads CLANG_TABLEGEN only
when it builds clang (src/bootstrap/src/core/build_steps/llvm.rs,
builder.config.llvm_clang), so clang-tblgen, the Generic CMake fallback,
bit.h and is_local_impl stand between M2 and clang and lld for a ToyOS host:
bootstrap-cannot-build-llvm-clang-and-lld-for-a-toyos-host.md, whose exit is
bootstrap installing a clang and an ld.lld for x86_64-unknown-toyos.
rustc_llvm's C++ runtime, C library and cross paths are M3's alone:
rustc-llvm-cannot-build-for-a-toyos-host.md keeps the rustc -vV exit. The
track lists each under its milestone.

Neither LLVM nor Rust changes for a ToyOS tool. The platform arms stay arms;
clang-tblgen and the cross paths name what ToyOS's own build must do
instead. Bootstrap finds clang-tblgen only in the CMake build directory of a
host LLVM it built itself, and rustc_llvm swaps the host triple in the host
llvm-config's paths, both of which hold for a bootstrap build directory and
neither for the store's. Bootstrap's ToyOS arm is refused by LLVM's
configure ("Unable to determine platform", HandleLLVMOptions.cmake at
849da7d62) until CMake sets UNIX, which only a platform module does
(Platform/UnixPaths.cmake), so the issue cites the CMake-platform one.

aligned_alloc's exit asks for the address to be a multiple of the requested
alignment, at 64 and 4096, and for free and realloc to release each block at
the layout it was allocated with. dlmalloc 0.2.14 checks a freed size and
ignores the alignment, so no case sees the second half; std's realloc
releases at alignment 16 as its free does.

The libc cases each read their effect back: F_GETFL on an O_RDWR | O_APPEND
descriptor, F_DUPFD at least its argument, chmod beside fchmod (LLVM's
setPermissions calls both); the old mask of a second pthread_sigmask or
sigprocmask, getrlimit after setrlimit, readlink of symlink, the file
through link's name. sigprocmask, an answer-0 stub LLVM calls from
Unix/Signals.inc, joins the POSIX issue, and SIGUSR1 returns to its signal.h
line, since the header-drift exit checks prototypes only. alarm(0) answers
1 to 5 after alarm(5) and 0 after that, since LLVM's Wait disarms with it
before restoring the old SIGALRM action. The pread race runs over a file
whose every 8-byte word holds its offset, today's pread and pwrite its
negative control, and a pwrite arm joins it. readdir never answers DT_REG
for a directory.

Removed: the LLD-precedent clause, the paragraph naming an open PR and a
file main does not have, and toyos-has-no-c-compiler-inside-it.md's copy of
the track's list, which returns to main's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
@Japabu

Japabu commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator Author

Round 3 at 94139d9e4. CI host SUCCESS at this head (run 36791219590, job 110144314783). The branch adds no tests and targets no hardware. Net +393 −0 against main, 12 files, all prose under issues/: production 0, tests 0. Since round 2, main's merge excluded (4b879ea6c..94139d9e4): +141 −98.

Round-2 BLOCKERs

  • B1 CLOSED. The issue is split. bootstrap-cannot-build-llvm-clang-and-lld-for-a-toyos-host.md sits under M2 Configure and Compile (toyos-builds-itself.md:56-64), and its exit, bootstrap with clang = true installing a clang and an ld.lld for x86_64-unknown-toyos, fails today on the clang-tblgen panic. That panic is read at src/bootstrap/src/core/build_steps/llvm.rs:534-541 at aca5f527f, under llvm_clang inside !is_host_target. rustc-llvm-cannot-build-for-a-toyos-host.md sits under M3 Build (:72-73) and keeps rustc -vV. Every M2 item blocks a C++ clang or lld. Every M3 item needs a Rust std binary. No citation of the deleted file is left outside rust/, and every issues/ path the 12 files cite resolves.
  • B2 CLOSED. The exit (a-rust-std-program-defines-no-aligned-alloc.md:25-30) asserts each address a multiple of 64 and of 4096. aligned_alloc = malloc(size) answers System.alloc(Layout(16 + size, 16)) + 16 (library/std/src/sys/pal/toyos/mod.rs, c_allocator), so that case goes red. The header layout is in the exit. A mismatch in alignment alone cannot be seen: dlmalloc 0.2.14's free is let _ = align; validate_size(ptr, size) (src/lib.rs:204-207). validate_size is an assert! (src/dlmalloc.rs:1252-1263), so a wrong base or a wrong size panics in the case's "frees each".

NOTE

  • issues/build/a-rust-std-program-defines-no-aligned-alloc.md:25-30: the exit claims realloc releases at the allocated layout, and the case never calls realloc. A fix that teaches free the header and leaves realloc's ptr.sub(HEADER) and Layout::from_size_align_unchecked(old_total, ALIGN) alone passes. Fix: the case reallocs the 4096 block to 1 MiB and asserts its first bytes carried. validate_size then asserts on the wrong base, and the case goes red.
  • issues/build/libc-fcntl-and-fchmod-answer-0-and-do-nothing.md:11,25-28: two stubs still pass the case. Line 11 says F_SETFL sets nothing, and the case reads only its answer, so case F_SETFL: return 0; passes once F_GETFL is right. case F_DUPFD: return arg; passes "no lower than its argument". Fix: the case sets O_NONBLOCK with F_SETFL and reads it back with F_GETFL, or F_SETFL answers -1 with errno. It also asserts that fstat of F_DUPFD's answer succeeds with the original's size.
  • issues/build/libc-fcntl-and-fchmod-answer-0-and-do-nothing.md:7: the heading now names chmod and the slug does not, and ls is the index (issues/README.md). Rename the file and its two citations (toyos-builds-itself.md:68, toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md:43).
  • issues/build/rustc-llvm-cannot-build-for-a-toyos-host.md:13-14,21-22: the item offers two paths to one answer. It names the switch that already selects c++ (LLVM_USE_LIBCXX, compiler/rustc_llvm/build.rs:491,505, or -stdlib=libc++ in the cxxflags, :530-531), then prescribes a ToyOS arm at the same site. Say which one the fix is.

REMOVE

  • none

LAND

@Japabu
Japabu added this pull request to the merge queue Sep 30, 2026
Merged via the queue into main with commit 49f4938 Sep 30, 2026
1 check passed
@Japabu
Japabu deleted the wt/toyos-rustcllvm branch September 30, 2026 23:54
Japabu added a commit that referenced this pull request Oct 1, 2026
#644's final review tightened what this must satisfy.

- aligned_alloc in a Rust std program is std's C allocator's now (the rust
  pin moves to 9151571cae9, one commit on aca5f527fcb): each block carries
  its size and alignment in front of it, as libc's own allocator does, and
  free and realloc release it at that layout. libc's std-runtime
  aligned_alloc, which answered std's malloc for an alignment to 16 and
  EINVAL above, goes with memreq::std_aligns and its test.
  tests/toyos-rust-tests/src/bin/c_aligned_alloc.rs allocates at 64 and
  4096, reallocs the 4096 block to 1 MiB and checks its first bytes carried,
  and frees each; dlmalloc asserts a released block's size, so a block
  released at another layout ends the program.
- fcntl's F_DUPFD answers a working duplicate at or above its argument, the
  first the kernel hands dup, the lower ones taken on the way closed again;
  a negative argument is EINVAL. F_DUPFD_CLOEXEC stays refused: close-on-exec
  is stage 3's. 206_libc_refusals fstats the duplicate for the file's byte.
- src/libc.rs's test module is at the end of the file, where clippy's
  items_after_test_module has it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Japabu added a commit that referenced this pull request Oct 1, 2026
…nto wt/toyos-libcllvm

No conflict. #644's issues cite
issues/build/libc-headers-are-written-by-hand-and-drift-from-its-definitions.md,
which this branch closed (its exit is toyos-libc-copies/src/prototypes.rs):
the five citations drop that path, and the track's points at the gate. The
issues this branch meets are closed, and the rest brought up to date, in the
commit after this one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Japabu added a commit that referenced this pull request Oct 1, 2026
…back

#644 landed the issues this branch's work answers. Each is met here and
deleted, or brought up to date:
- the-c-sysroot-has-no-libm-so-llvms-configure-fails: configure exits 0
  against this C sysroot with the eleven probes it names passing (measured,
  PR body). Its exit also names -lc: libc.a joins the empty libraries, and
  206_libc_refusals links with -lc -lm -lpthread -ldl -lrt
  (tests/common/compile.rs's LINK_FLAGS), so a sysroot missing one builds no
  corpus.
- libc-mmap-ignores-the-file-it-is-asked-to-map: a file, private or shared,
  at offset 0 or a later page, is ENODEV, each asserted by 206.
- libc-readdir-calls-every-entry-a-regular-file: 207 lists a file and a
  directory.
- libc-fcntl-and-fchmod-answer-0-and-do-nothing: every fcntl command does
  what POSIX says or answers -1 with errno, F_DUPFD's duplicate is fstat'd,
  and chmod and fchmod refuse with the mode read back through stat and fstat.
  What fcntl still refuses is libc-refuses-what-toyos-cannot-yet-answer's.
- a-rust-std-program-defines-no-aligned-alloc: std's aligned_alloc, the
  previous commit.
- toyos-libc-lacks-the-posix-surface-llvm-compiles-against: every name it
  lists is declared and defined, refused with errno, or (wait, wait4, the
  signal-set calls, alarm) stage 3's. madvise is new: Linux's four hints
  taken, its MADV_DONTNEED discard refused ENOSYS, anything else or an
  address off a page EINVAL, its rule memreq's and host-tested. 207 prints
  the macros and sizes LLVM reads, so the corpus is a compile and link probe
  of every name.
- libc-pread-and-pwrite-move-the-offset-another-thread-shares is renamed
  libc-has-no-pread-or-pwrite: they are gone, and its exit stands.
- toyos-builds-itself.md's M2 and M3 lists name what is left; libc-has-no-
  alarm.md and the bootstrap issue cite what stands instead of the closed
  POSIX issue, the bootstrap issue with the LLVM measurement.

The sysroot recipe moves (10): a C sysroot now holds libc.a.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Japabu added a commit that referenced this pull request Oct 1, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Japabu added a commit that referenced this pull request Oct 1, 2026
…toyos-noredlist

#588 landed first, and its `usb_stick_left` arms `usb-transport-break`,
`usb-reset-moves`, `usb-reset-moves-after` and `usb-reset-moves-configured`
again, its T14 row (`usbbreak`) arms `usb-transport-break`, and its metal
record carries the `usbbreak` rows. Those stay, with `msc::transport_break`,
`msc::reset_moves`, `RECOVERING` and `Quiet::Staged`. Everything else this
branch deleted with `usb_transport_break` (90ecefe, b5c59cb, 402107b,
9ebf080) stays deleted: no test on either side arms it.

Conflicts, every hunk:

- `kernel/src/actuator.rs`, two hunks. First: main's eight USB rows. Kept
  `usb_transport_break`, `usb_reset_moves`, `usb_reset_moves_after` and
  `usb_reset_moves_configured`, with `usb_reset_moves`' doc losing its
  citation of the deleted `usb_transport_break`; dropped
  `usb_transport_offline`, `usb_reset_break`, `usb_transport_break_owed` and
  `usb_transport_break_flushed`, armed only by the deleted
  `usb_transport_break`, `log_flush_retry` and `partition_claim_departure`.
  Second: dropped `watch_window` (`blocking_read_window`, deleted in
  dc62efc), kept #634's `handler_post`.
- `kernel/src/drivers/xhci/wait/msc.rs`, fourteen hunks, misaligned by #588's
  rewrite of the file. Resolved as main's file with this branch's deletions
  applied to it: `Asks` and `bot`'s `asks` argument at its five call sites;
  `transport_break`'s owed and flushed half (`WROTE`, `FLUSHED`,
  `AFTER_A_FLUSH`, `wrote`, `flushed`, their calls in `MscDevice::wrote` and
  the flush, and `arm`'s argument), so `arm` reads `usb-transport-break`
  alone; `return_silent` and its hook in `served`; `reset_break` and the
  wrapper around `climb`, whose body `climb_until_in_step` carries again;
  `short_read` and its hold and release around the data phase; `staged` and
  its checks in `bot`, the bad signature, the withheld CBW, the gone port and
  the unanswered wait; the bind's `slow_return` stall and INQUIRY staging, and
  `slow_return` itself; `read_serial`'s short ask. `reset_moves`, its three
  holds and `RECOVERING` are main's as they stand.
- `kernel/src/watch.rs`, one hunk: dropped the `window` module
  (`watch-window`), kept #634's `handler_post` module.
- `toyos-sched/src/watch.rs`, one hunk: the same, `window` dropped and
  `handler_post` kept.
- `src/lib.rs`, one hunk: kept #652's `pub mod n2`, dropped `pub mod redlist`.
- `tests/common/power.rs`, one hunk: main's only change there renamed
  `transport_break_chain`'s doc to `usb_stick_left`; its one caller is the
  deleted `usb_transport_break`, so it stays deleted.
- `tests/common/usb.rs`, one hunk holding main's whole `usb_transport_break`
  region. Kept #588's `Held`, `usb_stick_left`,
  `a_stick_that_left_under_its_rung`, `transport_break_on_metal`,
  `transport_break_recovered` (which `tests/checks/usb.rs` judges) and
  `broke_on`; the rest is `usb_transport_break`'s and stays deleted:
  `a_read_whose_first_wait_spent_its_budget_goes_out_again`,
  `serial_short_is_not_read`, `cpu_of`, `line_with`, `Moved`,
  `a_stick_its_reset_moved_carries_on`, `abandoned_write_is_taken_offline`,
  `no_command_was_refused`, `port_gone_is_left_to_the_teardown`,
  `control_requests`, `command_blocks`,
  `every_reset_is_followed_by_a_test_unit_ready`, `is_a_rungs_configuration`,
  `every_port_reset_is_followed_by_a_test_unit_ready`,
  `every_reset_is_followed_by_both_clears` and `transport_gives_up`.
- `tests/toyos.rs`, five hunks. `MACHINE_TESTS`: kept `usb_stick_left` and
  #634's `handler_post_without_a_pass`; dropped `usb_transport_break`,
  `xhci_full_speed_device` (5e42235), `blocking_read_window` and
  `user_copy_races_munmap` (7ea6be1). `METAL`: kept #588's `usb_stick_left`
  row. Dispatch: kept `usb_stick_left` and `handler_post_without_a_pass`;
  dropped `usb_transport_break`, `xhci_full_speed_device` and
  `smp_failed_ap_leaves_no_hole` (aedcf17).

Outside the conflicts:

- `kernel/src/drivers/xhci/wait/mod.rs`: `Quiet::Staged` and its line come
  back, which `transport_break::take` answers with; the auto-merge had taken
  9ebf080's deletion. The `reset_break` and `return_silent` hooks stay
  deleted.
- `src/metal.rs`: `FLASHABLE`'s `usb-transport-break` row comes back
  (b5c59cb took it), since `usb_stick_left`'s T14 arm flashes it.
- `issues/kernel/a-held-disk-waits-for-a-pass-no-cpu-takes-when-every-cpu-is-in-a-call-on-it.md`:
  records `4f2bea143`, this merge's second parent, as the tree holding #588's
  version of `usb_transport_break`, in place of the instruction to record it.
- `issues/boot-media/logd-ends-the-boots-log-on-one-refused-create-and-nothing-durable-says-so.md`:
  drops its citation of `power::transport_break_chain`, deleted in 90ecefe.

The `rust` gitlink is main's.

On this tree: `cargo run -- --build-only` exit 0; the kernel's `cargo check`
for x86-64 and AArch64, bare, with `boot-actuators` and with
`boot-actuators,test-actuators`, exit 0 each; `cargo test --test toyos-build
--no-run` exit 0, no warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant