# Fil-C

A memory-safe implementation of C/C++. Fil-C adds an LLVM IR pass that rewrites pointer operations to carry a shadow "capability" (an `AllocationRecord*`) alongside every pointer, performs bounds checks on every dereference, and runs a garbage collector to manage the lifetime of the capability records. The result is C/C++ that survives bounds violations, use-after-free, and type confusion without rewriting source code.

## How it works

Three ideas, in layers:

- **Shadow capability per pointer.** Every pointer is paired with an `AllocationRecord*` tracking its allocation's bounds (`visible_bytes`, `length`). Dereferences check bounds against this record. See [[simplified-model-of-fil-c]] for the full walkthrough.
- **Parallel shadow heap for stored pointers.** Each allocation has a `visible_bytes` array (user data) and an `invisible_bytes` array (same size, element type `AllocationRecord*`). When user code loads or stores a pointer in memory, Fil-C also loads/stores the capability from the parallel index. This is how capabilities survive being written through memory.
- **Parallel concurrent incremental GC (FUGC).** AllocationRecord objects are never freed explicitly; the GC handles them. This means forgetting `free` is not a leak, and use-after-free is safe (freed records get canonicalised to a single length-0 sentinel).

Additional production features: escape-analyzed locals get heap-promoted automatically, function pointers carry a distinct capability flag with a uniform ABI, and atomic pointer ops use custom lowering to preserve atomicity across the paired load.

See [[pointer-provenance]] — Fil-C is a concrete system that makes provenance semantics observable, because equal pointers can carry different `AllocationRecord*` values.

## Use cases

- Legacy C/C++ you want memory-safe without a full rewrite, typically as a bridge to eventual migration.
- A stronger alternative to [ASan](https://clang.llvm.org/docs/AddressSanitizer.html) for finding memory bugs.
- Safe compile-time evaluation in languages like Zig where compile-time and runtime share a language.
- A teaching example for memory-model concepts like provenance.

## Limitations

- **Performance cost is large.** Every dereference is a bounds check; every pointer load/store is doubled. Optimisations claw some of this back but not all.
- **Forces a GC into C/C++.** For systems where GC pauses are unacceptable, Fil-C isn't the right fit.
- **ABI changes.** Functions take paired `(pointer, AllocationRecord*)` arguments; interop with unmodified C code needs wrappers.
- **`memmove` semantics quirk.** Aligned multi-byte `memmove` moves shadow memory along with user bytes; misaligned or byte-wise copies don't. This can silently lose capabilities if code relies on unaligned memory layouts.

## Related

- [[simplified-model-of-fil-c]] — the step-by-step introduction this toolbox entry is based on
- [[pointer-provenance]] — the memory-model concept Fil-C demonstrates
- [[win32-stable-abi]], [[abi-stability]] — contrast: ABI stability as a *lack* of enforced safety
- [[yk]] — another LLVM-IR-rewriting project, for JIT rather than safety

Homepage: [fil-c.org](https://fil-c.org/). Technical deep dive: [Invisicaps](https://fil-c.org/invisicaps). Collector: [FUGC](https://fil-c.org/fugc).
