codegen-lang 1.0.0

Backend abstraction targeting LLVM, Cranelift, or bytecode.
Documentation
# codegen-lang v1.0.0 — stable

**1.0.** The public API is frozen and stable. v0.1.0 stood up the scaffold and the quality gates; v0.2.0 built the core — the `Backend` abstraction, the `Bytecode` reference backend, and the register-based `Program` it emits. This release ratifies that surface as the `1.0` contract: it follows Semantic Versioning, carries no breaking changes before `2.0`, and ships with the full test and benchmark suite verified on Linux, macOS, and Windows.

There is no breaking change from `0.2.0` — a `0.2.0` program compiles and behaves identically. The freeze adds only what hardens the release: two runnable examples, serialization round-trip coverage, and the stability documentation.

## What is codegen-lang?

A backend abstraction for compiler back ends. A front-end produces a function in SSA form with [`ir-lang`](https://crates.io/crates/ir-lang); codegen-lang lays that control-flow graph out as a linear stream of instructions a machine can run. `Backend` is the trait a target implements; `Bytecode` is the target shipped here — a small, register-based bytecode that is enough to inspect, serialize, and run generated code without a native code generator. A backend built on LLVM or Cranelift slots in behind the same trait.

```rust
use codegen_lang::compile;
use ir_lang::{Builder, BinOp, Type};

// fn double(x: int) -> int { x + x }
let mut b = Builder::new("double", &[Type::Int], Type::Int);
let x = b.block_params(b.entry())[0];
let sum = b.bin(BinOp::Add, x, x);
b.ret(Some(sum));

let program = compile(&b.finish()).unwrap();
assert_eq!(
    program.to_string(),
    "double(r0) regs=2\nL0:\n    r1 = add r0, r0\n    ret r1\n",
);
```

## The 1.0 surface

The frozen contract:

- **Abstraction** — the `Backend` trait (an associated `Output` and `compile`), so different targets produce different representations behind one interface.
- **Reference backend** — `Bytecode`, and the `compile` shortcut for the common case.
- **Output** — `Program` (name, parameter registers, register count, op stream, label resolution, and a disassembly `Display`), the closed `Op` instruction set, and the `Reg`, `Label`, and `Const` operands.
- **Errors** — `CodegenError`, with `InvalidIr` wrapping the `ir-lang` validation reason.
- **Re-exports** — `ir_lang::BinOp` and `ir_lang::UnOp`, the operations carried by `Op`.
- **Serialization** — `serde` for the program types under the `serde` feature.

`CodegenError` is `#[non_exhaustive]`, so a future backend reporting a target-specific failure is a non-breaking addition.

## SemVer promise

The crate follows [Semantic Versioning](https://semver.org):

- No documented item is removed or changed in a breaking way within `1.x`; breaking changes wait for `2.0`.
- New functionality is additive and arrives in minor releases. A new `CodegenError` variant, or a new `Backend` implementation, is a minor change.
- The MSRV is Rust `1.85`; raising it is a minor change, never a patch.
- Behaviour is part of the contract: a function that compiles today keeps compiling, and the disassembly `Display` form is stable for a given program.

The full statement lives in [`docs/API.md`](https://github.com/jamesgober/codegen-lang/blob/main/docs/API.md#semver-promise).

## Breaking changes

**None.** `1.0.0` makes no breaking change to the `0.2.0` surface.

## Hardening since 0.2.0

- **Runnable examples.** `cargo run --example disassemble` lowers `double`, `abs`, and a countdown loop and prints each one's disassembly; `cargo run --example inspect` walks a compiled program's op stream and shows a malformed function being rejected.
- **Serialization coverage.** Round-trip tests confirm a `Program` and a `CodegenError` survive `serde` serialization and deserialization unchanged, including the disassembly of the restored program.
- **Stability documentation.** The crate root, `README`, and `docs/API.md` now state the frozen `1.0` surface and the SemVer promise.

## Verification

Run on Windows x86_64 with WSL2 (Ubuntu), Rust stable 1.95.x and the 1.85 MSRV toolchain; the same commands run in the CI matrix across Linux, macOS, and Windows:

```bash
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo test --all-features
cargo build --no-default-features          # no_std build
cargo build --examples
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
cargo bench --bench bench --all-features --no-run
cargo +1.85 build --all-features           # MSRV
cargo deny check
cargo audit
```

All green. Test counts at this tag:

- Default features: 16 unit + 14 integration (6 workflow + 5 invalid + 3 property) + 15 doctests.
- `--all-features`: the above + 2 `serde` round-trip tests.
- Two runnable examples (`cargo run --example disassemble`, `cargo run --example inspect`).

## What's next

The `1.0` surface is stable until `2.0`. Future work is documentation, tests, and internal optimization that does not change the public contract — plus the additive room the design leaves: native backends (LLVM, Cranelift) behind the same `Backend` trait, and new `Op` forms to lower IR instructions that `ir-lang` adds in its own `2.0`.

## Installation

```toml
[dependencies]
codegen-lang = "1"
ir-lang = "1"

# no_std:
codegen-lang = { version = "1", default-features = false }

# with serialization:
codegen-lang = { version = "1", features = ["serde"] }
```

MSRV: Rust 1.85.

## Documentation

- [README](https://github.com/jamesgober/codegen-lang/blob/main/README.md)
- [API Reference](https://github.com/jamesgober/codegen-lang/blob/main/docs/API.md)
- [Roadmap](https://github.com/jamesgober/codegen-lang/blob/main/dev/ROADMAP.md)
- [CHANGELOG](https://github.com/jamesgober/codegen-lang/blob/main/CHANGELOG.md)

---

**Full diff:** [`v0.2.0...v1.0.0`](https://github.com/jamesgober/codegen-lang/compare/v0.2.0...v1.0.0).
**Changelog:** [`CHANGELOG.md`](https://github.com/jamesgober/codegen-lang/blob/main/CHANGELOG.md#100---2026-06-30).