This guide explains the code organization and development workflow for absolution.
absolution/
├── src/
│ ├── main.zig # CLI entrypoint and argument parsing
│ ├── root.zig # Library exports (Parser, cgen, Invariant)
│ ├── Parser.zig # C parsing via aro, global extraction
│ ├── Invariant.zig # .zon invariant loading and application
│ ├── type_flatten.zig # Type flattening (structs, arrays, unions → field list)
│ ├── include_paths.zig # Include path discovery (zig cc compatibility)
│ ├── seed.zig # initial seed generation
│ └── cgen/
│ ├── ir.zig # Core data structures (Domain, Field, Global)
│ ├── builder.zig # File writing utilities and type re-exports
│ └── emit.zig # C code emission (sampler, checker, entrypoint)
├── tests/ # Integration test cases
│ └── <test_name>/
│ ├── <file>.c # Test input
│ ├── <file>.c.in # Optional input invariant
│ └── <file>.c.zon # Golden output
├── scripts/
│ ├── integration.zig # Integration test runner (zig run scripts/integration.zig)
│ └── gen-golden.sh # Golden file generator
└── build.zig # Build configuration
CLI interface using the clap library:
- Parses command-line arguments
- Orchestrates the parse → generate → emit pipeline
- Writes seed file
Parses C translation units using aro:
- Initializes the aro toolchain and configures include paths (via
include_paths.zig) - Extracts non-const global variables
- Delegates type flattening to
type_flatten.zig - Deduplicates non-static globals across translation units
Flattens C types into a linear field list:
- Peels top-level array dimensions from globals
- Recursively flattens structs into dot-path field names
- Generates synthetic padding fields from layout gaps
- Handles arrays, unions, and bit-fields
Discovers and configures include search paths to match zig cc behavior:
- Adds target-specific, generic, and wildcard libc header directories
- Uses the bundled sysroot under
<prefix>/lib/... - Keeps absolution self-contained (no host system headers)
Handles .zon invariant files:
- Loads and parses invariant specifications
- Validates pointer domain targets
- Applies domain constraints to parsed globals
Core data structures:
Domain:.top,.values,.whole_values,.pointersField: Flattened field with name, width, dimensions, domainGlobal: Named global with dimensions and fields
C code emission:
writeFuzzerC: Writes includes, extern declarations, redef file, sampler, checker, and entrypointemitSampler: Generatessample_invariant()functionemitChecker: Generatescheck_invariant()functionemitEntrypoint: GeneratesLLVMFuzzerTestOneInput()
zig build # Build to zig-out/
zig build -fincremental # Incremental build (faster)
zig build run -- --help # Build and run with argszig build test # Unit tests (in-source)
zig build test --summary all # Verbose unit test output
zig run scripts/integration.zig # Integration tests
zig run scripts/integration.zig -- foo # Run only tests matching "foo"-
Create a directory under
tests/:tests/my_test/ -
Add a C file with the globals to parse:
// tests/my_test/myfile.c struct Foo { int x; }; struct Foo foo;
-
Generate the golden
.zonoutput:zig build zig-out/bin/absolution -t tests/my_test/myfile.c --zon tests/my_test/myfile.c.zon --redef /dev/null # Verify the output is correct -
The test runner automatically discovers new tests.
-
Run to verify:
zig run scripts/integration.zig
C file → aro Preprocessor → aro Parser → AST traversal → ParsedGlobal[]
- Uses aro's built-in preprocessor (self-contained, no external dependencies)
- Configures include paths from bundled libc headers via
include_paths.zig - System headers are automatically filtered via
Source.Kindtracking
Nested structures are flattened to dot-path field names:
struct { struct { int x; } inner; } outer;
// Becomes: .inner.xPadding is detected from layout gaps and emitted as ._padN fields.
The emitter produces C code with:
- Nested loops for array dimensions (global and field)
- Static tables for
.values,.whole_values, and.pointersdomains - Index-based selection for constrained domains;
.whole_valuescopies one blob per field instance
- Follow Zig standard library conventions
- Use
errdeferfor cleanup on error paths - Prefer
std.ArrayListUnmanagedfor fields to minimize allocations - Document public functions with
///doc comments
The project uses pre-commit hooks (see .pre-commit-config.yaml). Install with:
pip install pre-commit
pre-commit installAbsolution is completely self-contained at runtime. It uses:
- The bundled aro library for C parsing and preprocessing
- Bundled sysroot headers copied at build time to
zig-out/lib/
No external tools (zig, clang, gcc) are required at runtime.