Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions issues/build/a-rust-std-program-defines-no-aligned-alloc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# A Rust std program defines no aligned_alloc

In a Rust std program the C allocator is std's:
`rust/library/std/src/sys/pal/toyos/mod.rs` defines `malloc`, `calloc`,
`realloc` and `free`, and libc's allocator is not built beside std
(`userland/libc/src/memory.rs`, `feature = "std-runtime"`). Nothing defines
C11's `aligned_alloc`, which libc++abi calls for an over-aligned `operator new`
and in its fallback allocator: the link
`issues/build/a-rust-std-binary-cannot-link-the-cxx-runtime.md` describes
leaves it undefined, referenced from `libc++.a`'s `stdlib_new_delete.cpp` and
`fallback_malloc.cpp`.

Std's `free` and `realloc` release every block at alignment 16, the one its
`malloc` allocates at. The allocator under them, dlmalloc
(`rust/library/std/src/sys/alloc/toyos.rs`), checks a released block's size and
ignores its alignment, so a block allocated at a larger one and released at 16
is a layout mismatch nothing reports.

**Exit**: std's C allocator defines `aligned_alloc`, whose block's address is a
multiple of the requested alignment, and `free` and `realloc` release each
block at the layout it was allocated with, the block's header carrying its
alignment as libc's own allocator's does. A guest case in a Rust std program
allocates through `aligned_alloc` at alignments 64 and 4096, asserts each
address a multiple of its alignment, and frees each.
24 changes: 24 additions & 0 deletions issues/build/a-worktree-cannot-build-a-hosted-rustc-of-its-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
status: open
kind: tooling
opened: 2026-09-30
---

# A worktree cannot build a hosted rustc of its own

The ToyOS-hosted rustc is built by the primary checkout alone
(`src/toolchain.rs`'s `ensure`, under `Owner::Us`), from the primary's `rust/`
under the primary's `write_config`. A worktree's image with `hosted-rustc =
true` carries that one: refused by name when the worktree builds a compiler of
its own (`src/build.rs`, `env.primary_compiler`), and taken without a word when
only the worktree's `write_config` differs, so the image then carries a rustc
another tree's recipe built.

So no branch can put the hosted rustc it changes into a guest before it lands.
Carrying LLVM instead of Cranelift changes `write_config`'s hosted target and
the fork's `compiler/rustc_llvm`, and its guest test could run only after the
merge.

**Exit**: a worktree whose `write_config`, or whose fork's `compiler/` or
`src/bootstrap`, differs from the primary's builds a hosted rustc of its own,
keyed as `src/compiler.rs` keys a compiler, and its image carries that one.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# Bootstrap cannot build LLVM, clang and lld for a ToyOS host

M2's clang and lld (`issues/build/toyos-builds-itself.md`) are LLVM built for
`x86_64-unknown-toyos`. Read from the fork at `rust/` and from
`src/llvm-project` at `849da7d62`, not run, four things stop bootstrap's LLVM
step for that target:

- **`clang-tblgen`.** With `clang = true`, the step for a target that is not
the host panics unless `clang-tblgen` is in the CMake build directory of a
host LLVM bootstrap built itself
(`src/bootstrap/src/core/build_steps/llvm.rs`, `CLANG_TABLEGEN`). Every
compiler build here names the store's LLVM (`src/llvm.rs`) as the host's
`llvm-config`, so bootstrap builds no host LLVM and the file is never there.
- **Its CMake system.** `configure_cmake` names no system for a ToyOS target and
falls back to `Generic`, under which LLVM sets `LLVM_ON_UNIX` to 0
(`llvm/cmake/modules/HandleLLVMOptions.cmake`) and compiles no `Unix/`
implementation of `Support`.
- **`bit.h`.** `llvm/include/llvm/ADT/bit.h` includes `<endian.h>` on the
systems it lists and `<machine/endian.h>` on any other, ToyOS among them.
- **`is_local_impl`.** `llvm/lib/Support/Unix/Path.inc` reads the BSDs'
`MNT_LOCAL` on a system it does not list.

The last three are ToyOS arms at existing dispatch sites, written as upstream
would take them. ToyOS joins `bit.h`'s `<endian.h>` list, so libc carries
POSIX's `endian.h` and no BSD name
(`issues/build/toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md`).
Bootstrap's arm names the system `ToyOS`, which LLVM's configure refuses,
`Unable to determine platform`, until CMake knows ToyOS and sets `UNIX`
(`issues/build/the-cxx-runtime-names-toyos-to-cmake-as-unix.md`).

`clang-tblgen` is no arm, and neither bootstrap nor LLVM changes for it: ToyOS's
build builds the LLVM for a ToyOS host in a bootstrap build that built the
host's LLVM itself, as `src/llvm.rs` builds the store's, never in a compiler
build that names the store's.

**Exit**: bootstrap, with `clang = true`, installs a clang and an `ld.lld` for
`x86_64-unknown-toyos`.
28 changes: 28 additions & 0 deletions issues/build/libc-fcntl-and-fchmod-answer-0-and-do-nothing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# libc's fcntl, chmod and fchmod answer 0 and do nothing

`fcntl` (`userland/libc/src/posix_io.rs`) answers 0 to every command on every
descriptor: `F_DUPFD` names descriptor 0 as the duplicate, `F_GETFL` reads
every descriptor as read-only and blocking, `F_SETFL` sets nothing, and a
command it does not know is answered as done. `chmod` and `fchmod` answer 0 and
change nothing, and LLVM's `sys::fs::setPermissions` calls each
(`llvm/lib/Support/Unix/Path.inc`). Once `fcntl.h` declares the record locks
(`issues/build/toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md`),
LLVM's `sys::fs::tryLockFile` and `lockFile`, in the same file, take a lock
nothing holds. Close-on-exec, `F_GETFD` and `F_SETFD`, is the descriptor
table's of stage 3 of
`issues/kernel/a-childs-end-is-an-event-and-a-parent-takes-its-children-down.md`.

**Exit**: every other command POSIX defines for `fcntl` does what POSIX says or
answers -1 with `errno` set — a record lock `EINVAL`, as POSIX has a file that
supports no locking answer — and a command POSIX does not define answers
`EINVAL`; `chmod` and `fchmod` each change the mode `stat` and `fstat` read
back, or answer -1 with `errno` set. A guest C case asserts each command's
answer: `F_GETFL` on a descriptor opened `O_RDWR | O_APPEND` answers both, and
`F_DUPFD` a descriptor no lower than its argument. It asserts what `chmod` and
`fchmod` answer, and the mode `stat` and `fstat` then read.
26 changes: 26 additions & 0 deletions issues/build/libc-has-no-alarm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# libc has no alarm

libc neither declares nor defines `alarm`, and LLVM bounds its wait on a child
with one: a `SIGALRM` handler makes `wait4` answer `EINTR`
(`llvm/lib/Support/Unix/Program.inc`, `Wait`), so an LLVM built for ToyOS does
not link without it
(`issues/build/toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md`
measures that link). POSIX gives `alarm` no refusal, and its `SIGALRM` reaches
a handler only through the signals libc imitates from stage 3 of
`issues/kernel/a-childs-end-is-an-event-and-a-parent-takes-its-children-down.md`
on; this waits on that stage.

LLVM's `Wait` disarms it with `alarm(0)` and then restores the old `SIGALRM`
action (`llvm/lib/Support/Unix/Program.inc`), so an `alarm(0)` that disarms
nothing ends the process when the alarm fires under the default action.

**Exit**: `alarm` arms and disarms `SIGALRM` as POSIX says, which a guest C
case shows: a handler installed without `SA_RESTART` runs, and a `wait4` on a
child that has not ended answers `EINTR`; and after `alarm(5)`, `alarm(0)`
answers from 1 to 5 and a second `alarm(0)` answers 0.
28 changes: 28 additions & 0 deletions issues/build/libc-mmap-ignores-the-file-it-is-asked-to-map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# libc's mmap ignores the file it is asked to map

`mmap` (`userland/libc/src/posix_io.rs`) never reads its `fd` or `offset`, and
maps anonymous memory, `MAP_SHARED` as `MAP_PRIVATE`: a file mapping succeeds
and reads zeros, and what is written through a shared one never reaches the
file. The kernel maps no file (`kernel/src/syscall/vm.rs`). Read from LLVM at
`849da7d62`, not run:

- `MemoryBuffer` maps a file it reads, private and read-only, when the file is
at least four pages and needs no terminator past the mapping's end
(`llvm/lib/Support/MemoryBuffer.cpp`'s `shouldUseMmap`, with libc's
`sysconf(_SC_PAGESIZE)` answering 4096), so it reads such a file as zeros
and reports no error.
- `FileOutputBuffer`, through which lld writes its output, maps the output file
shared and writable (`llvm/lib/Support/FileOutputBuffer.cpp`), so lld writes
an output of zeros and reports success.

Each falls back, to `read` and to a buffer in memory, when the map fails.

**Exit**: `mmap` of a file, shared or private, at offset 0 or at a later page,
answers `MAP_FAILED` with `errno` `ENODEV`, and a guest C case asserts each and
that an anonymous mapping still maps.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# libc's pread and pwrite move the offset another thread shares

`pread` and `pwrite` (`userland/libc/src/posix_io.rs`) seek the descriptor to
their offset, read or write, and seek it back: three calls, nothing held
between them. POSIX has them leave the file offset alone. Here a `read`,
`write`, `lseek`, `pread` or `pwrite` of the same descriptor on another thread,
landing between those calls, reads or writes at the wrong offset, or has its
own moved. The ABI has no positional read or write (`toyos-abi/src/syscall.rs`
has `seek`). No header declares `pread`
(`issues/build/libc-headers-are-written-by-hand-and-drift-from-its-definitions.md`),
so LLVM's configure finds none; once it does, LLVM reads every file slice
through it (`llvm/lib/Support/Unix/Path.inc`, `readNativeFileSlice`).

**Exit**: `pread` and `pwrite` never move the descriptor's offset, which a
guest C case shows over a file whose every 8-byte word holds its own offset.
While one thread `read`s the file through, another `pread`s it at one offset,
and every word either reads holds the offset it was read from. While one
thread `write`s such words through a second file, another `pwrite`s one at its
offset, and every word of that file then holds its own offset. Today's `pread`
and `pwrite` are the negative control: the case is measured red against them.
19 changes: 19 additions & 0 deletions issues/build/libc-readdir-calls-every-entry-a-regular-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# libc's readdir calls every entry a regular file

`readdir` (`userland/libc/src/posix_io.rs`) answers `d_type` `DT_REG` for every
entry, a directory's too. libc ships no `dirent.h` yet
(`issues/build/libc-headers-are-written-by-hand-and-drift-from-its-definitions.md`);
once one defines `DTTOIF`, LLVM takes an entry's type from `d_type`
(`llvm/lib/Support/Unix/Path.inc`, `direntType`) and reads a directory as a
file.

**Exit**: `readdir` answers each entry's type, or `DT_UNKNOWN` where it does
not know it, which a guest C case shows over a directory holding a file and a
directory: the directory's entry answers `DT_DIR` or `DT_UNKNOWN`, never
`DT_REG`, and the file's `DT_REG` or `DT_UNKNOWN`.
28 changes: 28 additions & 0 deletions issues/build/rustc-llvm-cannot-build-for-a-toyos-host.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# rustc_llvm cannot build for a ToyOS host

M3's rustc (`issues/build/toyos-builds-itself.md`) carries LLVM through
`compiler/rustc_llvm`, whose `build.rs`, read from the fork at `rust/`, not
run, builds it for `x86_64-unknown-toyos` wrongly three ways:

- It links `stdc++` for a target it does not list unless bootstrap's
`use-libcxx` asks for `c++`, and ToyOS's one C++ runtime is `libc++`.
- It links no C library: a cross build asks `llvm-config` for no system
libraries.
- It finds a cross target's LLVM by replacing the host triple in the host
`llvm-config`'s paths, and the store's paths (`src/llvm.rs`) do not contain
it, so the replacement names the host's LLVM.

The C++ runtime and the C library are ToyOS arms at existing dispatch sites,
written as upstream would take them. The paths are no arm, and rustc does not
change for them: ToyOS's build hands the hosted rustc's build a host LLVM whose
paths hold the host triple where the ToyOS host's LLVM's hold
`x86_64-unknown-toyos`, as bootstrap's own build directory lays the two out.

**Exit**: bootstrap builds `rustc_llvm` for `x86_64-unknown-toyos`, and the
guest's `rustc -vV` prints `LLVM version:`.
34 changes: 34 additions & 0 deletions issues/build/the-c-sysroot-has-no-libm-so-llvms-configure-fails.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
status: open
kind: defect
opened: 2026-09-30
---

# The C sysroot has no libm, so LLVM's configure fails

LLVM's configure adds `m` to every link probe on a `UNIX` system that is not
Apple, BeOS or Haiku (`llvm/cmake/config-ix.cmake`), and probes `pthread`, `c`,
`dl` and `rt` as libraries. The C sysroot's `lib/` holds `libtoyos_c.a` and no
archive under any of those names, so every probe that links fails.

Configuring `src/llvm-project/llvm` at `849da7d62` for `x86_64-unknown-toyos`,
with CMake's system `ToyOS` and `UNIX=ON`, against #637's C sysroot
(`de0de8ee7862147a`): `unable to find library -lm` 18 times, and exit 1 at
`cmake/modules/CheckAtomic.cmake:59`, "Host compiler appears to require
libatomic, but cannot find it". With empty `libm.a`, `libpthread.a`, `libdl.a`
and `librt.a` beside `libtoyos_c.a`, the same configure exits 0, and these
probes pass that failed: `HAVE_CXX_ATOMICS_WITHOUT_LIB`,
`HAVE_BUILTIN_THREAD_POINTER`, `HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC`,
`C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW`, `sysconf`, `isatty`,
`strerror_r`, `setenv`, `dlopen`, `dlopen` in `dl` and `pthread_create` in
`pthread`.

`pread` is not found in either: no header declares it
(`issues/build/libc-headers-are-written-by-hand-and-drift-from-its-definitions.md`),
and once one does, LLVM reads through
`issues/build/libc-pread-and-pwrite-move-the-offset-another-thread-shares.md`.

**Exit**: that configure exits 0 against the C sysroot as `src/libc.rs` lays it
out, with those eleven probes passing, and a host test links a C probe with
each of `-lm`, `-lpthread`, `-lc`, `-ldl` and `-lrt` against that sysroot with
the toolchain's clang.
27 changes: 27 additions & 0 deletions issues/build/toyos-builds-itself.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,30 @@ by the ToyOS-hosted rustc
(`issues/build/the-hosted-rustc-names-a-linker-toyos-does-not-have.md`). It
goes when lld runs in the guest: the row, the crate and its host tests go together, the hosted rustc names `rust-lld`, and
the published crates.io crate is yanked.

**What stops M2: LLVM, clang and lld built for a ToyOS host**, in the order
each blocks the next.
- Configure: the `clang-tblgen` and the CMake system of
`issues/build/bootstrap-cannot-build-llvm-clang-and-lld-for-a-toyos-host.md`,
and `issues/build/the-c-sysroot-has-no-libm-so-llvms-configure-fails.md`.
- Compile: `issues/build/toyos-libc-lacks-the-posix-surface-llvm-compiles-against.md`,
with the names it leaves to
`issues/build/libc-headers-are-written-by-hand-and-drift-from-its-definitions.md`,
and the bootstrap issue's `bit.h` and `is_local_impl`.
- Link: the POSIX issue's functions, with those it leaves to the child-process
track's stage 3 and to `issues/build/libc-has-no-alarm.md`.
- Run: `issues/build/libc-mmap-ignores-the-file-it-is-asked-to-map.md`,
`issues/build/libc-fcntl-and-fchmod-answer-0-and-do-nothing.md`,
`issues/build/libc-pread-and-pwrite-move-the-offset-another-thread-shares.md`
and `issues/build/libc-readdir-calls-every-entry-a-regular-file.md`.

**What M3 adds: a rustc that carries that LLVM**, after all of M2's.
- Build: `issues/build/rustc-llvm-cannot-build-for-a-toyos-host.md`.
- Link: `issues/build/a-rust-std-binary-cannot-link-the-cxx-runtime.md` and
`issues/build/a-rust-std-program-defines-no-aligned-alloc.md`.
- Test: `issues/build/a-worktree-cannot-build-a-hosted-rustc-of-its-own.md`.

M3's exit then waits on a linker in the guest
(`issues/build/the-hosted-rustc-names-a-linker-toyos-does-not-have.md`), which
toyos-ld is not: it refuses every executable with thread-local storage, so
every std program.
Loading
Loading