removing the need for panic and _start snippets in user space binaries

This commit is contained in:
Daniel Samson
2026-07-17 16:15:30 +01:00
parent 9989ebbec7
commit f309ce04f4
33 changed files with 71 additions and 175 deletions
+19
View File
@@ -0,0 +1,19 @@
//! The root module every user binary is compiled through (build.zig,
//! `addUserBinary`). The program's own file is imported as `program`, and this
//! shim contributes the declarations Zig resolves from the compilation root —
//! `main` (dispatched by runtime.start) and the panic handler — and pulls in the
//! `_start` entry shim. A program therefore only defines `pub fn main`; nothing
//! else is required in its source file.
const runtime = @import("runtime");
const program = @import("program");
/// Resolved as `@import("root").main` by runtime.start's comptime dispatch.
pub const main = program.main;
/// The panic handler for every safety check in the image (runtime.start.panic).
pub const panic = runtime.panic;
comptime {
_ = &runtime.start._start; // pull the runtime entry shim into the image
}
+6 -7
View File
@@ -4,12 +4,11 @@
//! shim. It is compiled into each binary (inheriting its `.large` code model and
//! freestanding target), so all user programs share one implementation.
//!
//! A user binary needs three lines:
//! const runtime = @import("runtime");
//! pub const panic = runtime.panic;
//! comptime { _ = &runtime.start._start; } // pull the entry shim in
//! and a `pub fn main() void` or `pub fn main(init: runtime.process.Init) void`
//! (arguments arrive via `init`).
//! A user binary only defines a `pub fn main() void` or
//! `pub fn main(init: runtime.process.Init) void` (arguments arrive via `init`).
//! The panic handler and the `_start` entry pull live in the shared compilation
//! root, library/runtime/root.zig, which build.zig wires around every program —
//! nothing to declare per source file.
pub const system = @import("system.zig");
/// Monotonic time, delays, and deadlines over the kernel clock/sleep/timer syscalls
@@ -65,7 +64,7 @@ pub const scanout_protocol = @import("scanout-protocol");
/// `std.os.danos` are staged. See docs/zig-self-hosting.md.
pub const fs = @import("fs.zig");
/// Re-exported so a user binary can `pub const panic = runtime.panic;`.
/// Re-exported so the root shim (root.zig) can install it as the panic handler.
pub const panic = start.panic;
/// Process entry types: the `Init` handed to `main`, and its `Arguments`.
+4 -3
View File
@@ -1,6 +1,7 @@
//! The user-space process entry shim. Every user binary roots `_start` here (via
//! `entry = _start` in build.zig) and forces this file to be analysed with
//! `comptime { _ = &runtime.start._start; }`, so the whole runtime is linked in.
//! `entry = _start` in build.zig); the shared compilation root, root.zig, forces
//! this file to be analysed with `comptime { _ = &runtime.start._start; }`, so
//! the whole runtime is linked in.
const std = @import("std");
const system = @import("system.zig");
@@ -36,7 +37,7 @@ export fn rt_start(stack: [*]const u64) callconv(.c) noreturn {
/// Comptime-dispatch on root.main's signature, in the spirit of std's start.zig:
/// zero parameters or one `process.Init`; returns void, noreturn, u8, !void, or !u8.
fn callMain(init: process.Init) u8 {
const root = @import("root"); // the user binary's root source file
const root = @import("root"); // root.zig, re-exporting the program's main
const main_information = @typeInfo(@TypeOf(root.main)).@"fn";
const call_arguments = switch (main_information.params.len) {