Architecture
This page describes the source layout of lib/basalt/, the 44 Rust modules that make up basaltc, the include tree, the build artifacts, and the strict dependency direction between basalt and trona.
Repository Layout
basalt lives at lib/basalt/ in the SaltyOS tree:
| Directory | Contents |
|---|---|
|
basaltc — the Rust C standard library, headers, linker scripts, and architecture-specific assembly. Built into |
|
44 top-level Rust modules implementing the public C ABI. Each module is a thin Rust file declaring |
|
Architecture-specific subtrees ( |
|
FreeBSD compatibility layer: 16 modules that implement BSD-only APIs ( |
|
118 C headers covering POSIX, BSD extensions, and SaltyOS-specific additions. Subdirectories: |
|
Per-architecture linker scripts for |
|
libc++ build wrapper. Compiles libcxx + libcxxabi + libunwind from |
The top-level entry point is lib/basalt/meson.build, which delegates to c/meson.build and (if the LLVM submodule is present) cpp/meson.build.
basaltc Module Map
The 44 modules in lib/basalt/c/src/lib.rs group into nine categories.
Each category corresponds to one or more documentation pages in this site.
| Category | Modules | Documentation |
|---|---|---|
Process runtime |
|
|
File and stream I/O |
|
|
Processes, signals, threads |
|
|
Text and locale |
|
Strings and Memory, Locale, ctype and wchar, Regular Expressions |
Time and math |
|
|
Networking |
|
|
Environment and identity |
|
|
Terminal and search |
|
|
Architecture and compatibility |
|
The compat::freebsd subtree contains 16 modules ported from FreeBSD: bsd_err, bsd_flags, bsd_io, bsd_misc, bsd_sort, bsd_stdio, cap_fileargs, capsicum, libutil, login_cap, md5, mntent, rune, statvfs, umtx, xo.
See FreeBSD Compatibility for which are real implementations and which are stubs.
Header Layout
lib/basalt/c/include/ is the public C ABI surface, with 118 headers organized by POSIX section:
| Subdirectory | Coverage |
|---|---|
(top level) |
75 headers: POSIX core ( |
|
23 headers: |
|
Internet and network headers: |
|
Capsicum capability-mode wrappers: |
|
|
|
OpenPAM headers ( |
|
Architecture-private machine definitions referenced by some |
Build Artifacts
Building basalt produces five distinct artifacts:
| Artifact | Producer | Consumer |
|---|---|---|
|
|
Every dynamically linked C/C executable. DT_NEEDED in libc. |
|
|
Linked into |
|
|
Linked statically into each executable. Defines |
|
|
Every C++ executable. DT_NEEDED on |
|
|
Other Rust crates that need to call into basaltc as a Rust crate, including the runtime dynamic linker and selected userland servers. |
Dependency Direction
basalt depends on trona; trona depends on the kernel ABI (UAPI); nothing depends back upward. The build enforces this:
Concretely, lib/basalt/c/meson.build declares --extern trona=libtrona.rmeta and --extern trona_posix=libtrona_posix.rmeta for the rustc invocation that compiles basaltc.
The link step adds -L libtrona_build_dir -ltrona so that libc.so carries a DT_NEEDED entry for libtrona.so.
There is no --extern basaltc anywhere in trona — the dependency is one-way.
For details on which basaltc modules talk to which trona_posix functions, see trona Boundary.
Architecture Abstraction
basaltc supports x86_64 and aarch64 through the arch module.
Three traits — ArchMath, ArchMem, ArchString — declare the operations whose implementations differ per CPU.
Each architecture provides a concrete type (X86_64Arch, AArch64Arch) implementing the traits, and lib/basalt/c/src/arch/mod.rs defines pub type Arch = … selected by #[cfg(target_arch)].
Generic code calls Arch::sqrt(x), Arch::memcpy(…), etc., and the compiler monomorphizes to the concrete type with no runtime branch.
The trait surface covers:
-
Math:
sqrt,floor,ceil,sin,cos,tan,atan2,log,log2,log10,exp,exp2,pow,fmod,remainder,fma,scalbn, plussqrtf,trunc,rint. -
Memory:
memcpy,memset,memmove,memcmp,memchr. -
String:
strlen.
Functions that do not benefit from SIMD (fpclassify, copysign, fabs, strcpy, strcmp) live in the generic modules and use Arch::* only as building blocks.
The x86_64 backend has two math implementations side by side: math_x87.rs (legacy x87 80-bit FPU) and math_sse2.rs (SSE2 packed double).
SSE2 is the default; the arch::x86_64 selection happens in mod.rs at compile time.
The aarch64 backend uses NEON for everything and has a single mod.rs covering math, memory, and string.
See Multi-Architecture Dispatch for the full trait definitions and the concrete code generation.
Safety Model
#![no_std]Rust-
basaltc uses only
core, neveralloc. The heap allocator is implemented inside basaltc (via malloc.rs), so the order of operations matters: code that runs before the allocator is up cannot allocate. - Single FFI surface
-
Every public C function is
#[unsafe(no_mangle)] pub extern "C"in a Rust module. There is no hand-written C wrapper layer. Pointer translation, errno mapping, and length conversion all happen inside the Rust function. - Errno is thread-local
-
errno_location()returns a pointer into the current thread’strona_posix::tls::Tlsstruct. A pre-TLS fallback global handles the brief window beforelibc_start_maininitializes TLS. See trona Boundary. - Unsafe blocks are explicit
-
Rust 2024 edition rules apply: every unsafe operation inside an
unsafe fnrequires an explicitunsafe {}block.static mutreferences are forbidden — basaltc usesaddr_of!/addr_of_mut!andSyncUnsafeCellfor global mutable state. Everyunsafeblock carries a// SAFETY:comment. - No panic in production paths
-
Panics ultimately call into
trona’s panic handler. basaltc avoids `.unwrap()and.expect()outside startup code; failures map to errno values returned through the C ABI.
Related Pages
-
Build System — how Meson drives rustc, clang, and lld to produce the artifacts above.
-
CRT Startup — what happens between
_startandmain. -
trona Boundary — module-by-module map of trona vs pure-Rust dependencies.
-
xref:cxx/cxx-runtime.adoc[libc Runtime] — how the C side is composed and built.