iter emit-ir-staticlib: ail emit-ir --emit=staticlib (M1 fieldtest spec_gap#2)

Restores the Decision-5 IR-readability affordance for main-free
kernels: ail emit-ir gains --emit=staticlib, symmetric with
ail build, reusing the M1-audited Target::StaticLib path via a new
one-line lower_workspace_staticlib convenience. Zero-export guard
byte-identical to build_staticlib's. DESIGN.md widened (not
narrowed) + a pre-existing M1 synopsis omission corrected. 3 new
E2E tests; no fixture minted, no doc pin (E2E is the coverage).
Plan 03493c9.
This commit is contained in:
2026-05-18 16:08:33 +02:00
parent 03493c9b31
commit bcfe554686
7 changed files with 194 additions and 4 deletions
+21 -2
View File
@@ -116,6 +116,14 @@ enum Cmd {
path: PathBuf,
#[arg(short, long)]
out: Option<PathBuf>,
/// IR shape. `exe` (default): whole-program IR (requires an
/// entry `main`). `staticlib`: kernel IR for a `main`-free
/// module — one external C forwarder per `(export "<sym>")`
/// fn, no `@main` (Embedding ABI M1). Same `Target` the
/// `build --emit=staticlib` path uses; output is the IR text
/// (stdout, or `-o <file>`), not archives.
#[arg(long, default_value = "exe", value_parser = ["exe", "staticlib"])]
emit: String,
},
/// Full pipeline: check + emit-ir + clang -> binary.
Build {
@@ -637,7 +645,7 @@ fn main() -> Result<()> {
);
}
}
Cmd::EmitIr { path, out } => {
Cmd::EmitIr { path, out, emit } => {
// Iter 5c: workspace lowering. For single-module programs the
// workspace is effectively a trivial workspace with one module.
let ws = load_workspace_human(&path)?;
@@ -687,7 +695,18 @@ fn main() -> Result<()> {
};
let ws = ailang_check::monomorphise_workspace(&ws)
.map_err(|e| anyhow::anyhow!("monomorphise_workspace: {e}"))?;
let ir = ailang_codegen::lower_workspace(&ws)?;
let ir = if emit == "staticlib" {
let has_export = ws.modules.values().any(|m| m.defs.iter().any(|d|
matches!(d, ailang_core::Def::Fn(f) if f.export.is_some())));
if !has_export {
anyhow::bail!(
"staticlib target needs at least one `(export \"<sym>\")` fn"
);
}
ailang_codegen::lower_workspace_staticlib(&ws)?
} else {
ailang_codegen::lower_workspace(&ws)?
};
match out {
Some(p) => {
std::fs::write(&p, ir)?;