System Primitives and Runtime
This page describes the operational clean LLVM compiler. Low-level operations are part of seed itself, not an addon language, but ordinary applications should consume narrow audited safe wrappers.
Runtime profiles
| Profile | Meaning |
|---|---|
hosted |
platform runtime services selected by the target |
freestanding |
libc-free image with explicitly selected services |
kernel |
kernel ABI/service restrictions and no hosted assumptions |
none |
no runtime services beyond target/compiler primitives |
Effects (alloc, blocking, panic, I/O) are checked against the selected
profile/service set. Profiles do not change ownership/type semantics.
Linux-native hosted execution has no mandatory libc. linux-libc is an
explicit interoperability runtime choice. Freestanding/kernel targets remain
libc-free.
Typed raw memory
unsafe fn use_buffer() -> result<i64, alloc_error> {
let pointer = raw_try_alloc<i64>(4)?
raw_write<i64>(pointer, 0, 42)
let value = raw_read<i64>(pointer, 0)
raw_free<i64>(pointer)
result.ok(value)
}
An extern ABI that returns process/static-lifetime view storage may declare
@static_view. This is a trusted provenance assertion restricted to extern;
the call remains unsafe and an ordinary safe library wrapper must audit the
foreign lifetime guarantee.
The clean unsafe substrate is raw_try_alloc<t>, raw_null<t>,
raw_is_null<t>, raw_read<t>, raw_write<t>, raw_free<t>, and
raw_slice<t>. Allocation rejects negative counts, multiplication overflow,
and allocator failure with alloc_error.
Unsafe callers remain responsible for extent, alignment, initialization,
provenance, aliasing, and exact-once element release.
raw_null<t>() produces the internal null sentinel used by audited unsafe
owners, and raw_is_null<t>(pointer) tests it. The standard box<t> confines
those operations behind its constructor, consuming extraction, and destructor.
Linux-native allocations whose payload plus header fits 8 KiB and whose alignment is at most 16 bytes use precise slab classes (16 bytes through 8 KiB). Empty 1 MiB slabs share a process-wide 32-entry cache; excess empty slabs are unmapped. Larger or more strictly aligned allocations remain page-rounded direct mappings and are unmapped immediately.
The native runtime also supplies optimizer-introduced memcpy, memmove, and
memset entry points without libc. Its sqrt(f64) runtime symbol lowers to the
LLVM square-root intrinsic, allowing strict floating-point workloads to remain
libc-free.
Legacy alloc(type,n), integer-address read/write, and free examples
belong to archived backends and are not the clean compiler API.
Address spaces and devices
Raw pointer types may identify user, kernel, physical, mmio, or dma
address spaces. They remain distinct through .sdi and LLVM lowering. Typed
volatile operations and explicit unsafe mapping/cast transitions are used for
device memory. compiler/llvm/libs/system builds safe nominal wrappers for
MMIO, pages, pin/DMA, initialization, and CPU-local mechanisms.
Atomics
The compiler validates acquire/release helpers and explicit ordered load, store, fetch-add, exchange, compare-exchange, and fence operations. Invalid load/store/CAS ordering combinations are rejected. Atomics are distinct from volatile device access. A safe wrapper must establish allocation lifetime, alignment, shared access, and a consistent atomic protocol.
FFI and ABI
The target/ABI layer assigns explicit internal seed, public seed, platform-C,
compiler-builtin, entry, interrupt, and naked ABI classes. .sdi includes
target, ABI, build-profile, runtime-profile, and runtime-feature identity;
known seed artifact mismatches fail closed with a rebuild diagnostic. Foreign
C/assembly objects have no seed profile metadata and remain explicitly
linkable.
Covered FFI boundaries include scalars, raw pointers, non-capturing callbacks, opaque handles, and pointer-based scalar C-struct wrappers. By-value C structs and richer platform ABI modeling remain limited. Foreign calls are unsafe until wrapped by a checked safe API.
Panic and cleanup
Safe check failure invokes the target panic/trap policy. Panic, trap, and abort never unwind across seed, FFI, dynamic-library, interrupt, kernel/user, or task boundaries. No lexical cleanup or user destructor runs on those edges.
Separate runtime and libraries
Compiler-builtins use stable runtime symbol IDs rather than source-name string inspection. Hosted executable runtime services include allocation/resource operations, process entry/args/environment, output/files, time/randomness, network descriptors, scheduler hooks, regions, panic, and abort at the level implemented by each target row.
seed_runtime_format_write consumes the stable immediate format_args
descriptor and writes each {pointer, byte_length} piece without building a
contiguous buffer. format_args.to_string() instead uses the selected
allocator and reports failure as alloc_error; neither path requires libc.
Dynamic libraries declare required runtime symbols and resolve against the
executable/runtime domain. Installed libraries are target/ABI qualified;
dynamic linkage is default and --static selects static seed archives.
Process libraries use the public seed_runtime_process_* boundary. Native
entry-vector primitives such as seed_process_argc remain hidden inside the
executable and are reached only through exported runtime wrappers.
Target levels
The declarative target matrix separates LLVM/object emission from static link, dynamic link, executable, and run levels.
- Linux x86-64: closed hosted and libc-free native default.
- Linux AArch64: hosted runtime/link with runner policy.
- Linux RISC-V64: hosted object-only; freestanding boot is separate.
- Windows x86-64: PE/DLL/runtime/tasks/networking, file read/seek, shared-byte ownership, Microsoft x64 aggregate-parameter FFI, loader hardening, and a relocatable SDL3 game package pass under the required Wine policy.
- macOS x86-64: explicit-SDK executable/dylib/static/runtime/pthread surface is ready for the required native Intel run.
- macOS arm64: the equivalent surface is cross-link verified; execution is not claimed without a runner.
- Android arm64 and x86-64: LLVM/object emission, static libraries, shared
libraries and simple executables with an explicit NDK sysroot, plus
.sdiinterfaces, are available as an initial mobile target slice. The native adapter covers allocation/regions, tasks, I/O/filesystem/socket wrappers, Logcat, process/time/entropy, ownership builtins, and lifecycle cancellation; the Android-onlymobilelibrary andSeedSurfaceViewprovide bounded frame primitives/text, touch/key/IME input, safe-area/display metrics, focus and memory-pressure signals, private files/cache directory views, and an atomic private integer-slot store for small progress/settings values; a Gradle/CMake/Kotlin/JNI host template, ABI-awarejniLibsstaging, package/run commands, and doctor diagnostics are available. Emulator/device execution and production signing remain unverified without an Android toolchain and runner. - freestanding x86-64/AArch64/RISC-V64: libc-free boot evidence at Gate 7 declared levels.
- Wasm/WASI services remain explicit at their declared matrix level.
See seed/compiler/llvm/tests/GATE14_TARGET_MATRIX.tsv rather than inferring
capabilities from the presence of an LLVM triple.
Boot meaning
For Gate 7, “boot” means the compiler emits a target image, QEMU system emulation loads it through the declared firmware/machine path, target entry code executes, writes the expected success evidence through the target mechanism, and exits or reaches the expected terminal state. It does not mean that a full operating system, driver stack, userspace, or libc is present.
Release profiles
--release and --release-small preserve safe checks. LLVM may remove checks
only when proved redundant. ThinLTO, PGO, static linkage, code/relocation model,
red-zone policy, entry, linker script, target, runtime profile, and sysroot are
explicit independent controls.