docs: add libVCT public specification set (000-015)
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
# 013 — Build & Packaging
|
||||
|
||||
- **Status:** Draft
|
||||
- **Normative language:** `MUST`, `MUST NOT`, `SHOULD`, `SHOULD NOT`, and `MAY` are to be
|
||||
interpreted as described in RFC 2119.
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This file specifies how libVCT is built, what it produces, what it exposes to embedders, and who
|
||||
owns memory across the API boundary. It also fixes the configuration, threading, versioning, and
|
||||
determinism contracts that the rest of the specification depends on.
|
||||
|
||||
## 2. Scope
|
||||
|
||||
Covers the toolchain, the build system, the shipped artifacts, the two API surfaces, module
|
||||
visibility, arena ownership, the `Config` struct, the threading contract, versioning, and the
|
||||
determinism guarantee. It does not restate stage semantics; those live in the stage files.
|
||||
|
||||
## 3. Definitions
|
||||
|
||||
| Term | Meaning |
|
||||
|---|---|
|
||||
| **C API** | The `extern(C)` surface exposed to non-D callers. |
|
||||
| **D API** | The native D surface; the implementation itself. |
|
||||
| **Shim** | The thin translation layer implementing the C API over the D API. |
|
||||
| **Arena** | A region of memory reclaimed as a unit, not per object. |
|
||||
| **Bump allocator** | The default in-tree allocator that serves requests by advancing a pointer. |
|
||||
| **Cold path** | Code that runs at most a few times per compilation: driver, diagnostics, CLI. |
|
||||
|
||||
## 4. Toolchain
|
||||
|
||||
1. The library **MUST** be written in D.
|
||||
2. Release builds **MUST** use LDC2, chosen for generated-code quality.
|
||||
3. Debug builds **MUST** use DMD, chosen for compile and iteration speed.
|
||||
4. libVCT **MUST** have zero runtime dependencies beyond its own code. It **MUST NOT** require a
|
||||
third-party library at build time or at load time.
|
||||
5. A D compiler is required to build libVCT. A system C compiler is required only when the C path
|
||||
is used, and it **MUST** be discovered at runtime (see [010 — Driver & CLI](010-driver-cli.md)).
|
||||
Prebuilt binaries **MUST NOT** require a D compiler at load time.
|
||||
|
||||
## 5. Build system
|
||||
|
||||
6. The build system **MUST** be xmake. A single `xmake.lua` **MUST** drive every target.
|
||||
7. The build system **MUST NOT** be dub.
|
||||
8. The `release` profile **MUST** select LDC2. The `debug` profile **MUST** select DMD.
|
||||
9. Building libVCT **MUST NOT** require an external package manager.
|
||||
|
||||
## 6. Artifacts
|
||||
|
||||
10. A conforming build **MUST** produce all of the following:
|
||||
|
||||
| Artifact | Kind | Purpose |
|
||||
|---|---|---|
|
||||
| `libvct.a` | static library | Static linking of the full library. |
|
||||
| `libvct.so` | shared library | Dynamic linking; embedders load it at runtime. |
|
||||
| `vct` | executable | The command-line driver (see [010 — Driver & CLI](010-driver-cli.md)). |
|
||||
| `vctc.h` | C header | The declarations of the C API. |
|
||||
| `vct.test.hirbuild` | D module | The fixture harness, shipped publicly (see [012 — Testing](012-testing.md)). |
|
||||
|
||||
11. The static and shared libraries **MUST** expose the same symbols and behavior; choosing one
|
||||
over the other **MUST NOT** change observable results.
|
||||
|
||||
## 7. Public API surfaces
|
||||
|
||||
12. The **C API** **MUST** be the primary public surface in v1. It **MUST** be declared
|
||||
`extern(C)` so that C, C++, and other FFI callers can use it without a D toolchain.
|
||||
13. The C API **MUST** represent library state through opaque handles for `Context`, `Module`,
|
||||
`Builder`, and `Config`. Callers **MUST NOT** depend on the layout of these types, and the
|
||||
header **MUST NOT** expose their internal fields.
|
||||
14. The C API **MUST** provide operations to build IR, run the pipeline, and query diagnostics.
|
||||
15. The **D API** **MUST** be the full-feature implementation surface. The C API is a shim over
|
||||
it.
|
||||
16. The shim **MUST NOT** contain logic beyond argument marshalling, error translation, and
|
||||
handle conversion. Every behavior reachable through the C API **MUST** be implemented in the
|
||||
D API, so that every C API call exercises the D API.
|
||||
17. An implementation **MUST NOT** place optimizer, lowering, or backend logic in the header or
|
||||
the shim.
|
||||
|
||||
An illustrative header shape (not a complete declaration set):
|
||||
|
||||
```c
|
||||
typedef struct vct_context vct_context;
|
||||
typedef struct vct_module vct_module;
|
||||
typedef struct vct_builder vct_builder;
|
||||
typedef struct vct_config vct_config;
|
||||
|
||||
vct_context *vct_context_create(const vct_config *cfg);
|
||||
void vct_context_destroy(vct_context *ctx);
|
||||
```
|
||||
|
||||
## 8. Module visibility
|
||||
|
||||
18. The following modules **MUST** be public: `vct.ir.hir`, `vct.traits`, `vct.context`, the
|
||||
entry points of `vct.backend.c` and `vct.backend.llvm`, `vct.driver`, `vct.diag`, and
|
||||
`vct.test.hirbuild`.
|
||||
19. The following modules **MUST** be internal: `vct.ir.vir`, `vct.lower`, `vct.hir.opt`,
|
||||
`vct.vir.opt`, and the internals of `vct.comptime`.
|
||||
20. A public module **MUST NOT** expose internal types in its public signatures in a way that
|
||||
forces embedders to depend on internal layout. The trait vocabulary and node identity cross
|
||||
this boundary and are versioned accordingly (see section 12).
|
||||
|
||||
## 9. Memory ownership and lifecycle
|
||||
|
||||
21. A `Context` **MUST** own one or more arenas. An arena is the unit of reclamation. The default
|
||||
is one arena per `Module`, freed wholesale.
|
||||
22. All IR and optimizer objects **MUST** be arena-owned and non-GC. Passes **MUST** mutate them
|
||||
in place under epoch guards (see [002 — Traits](002-traits.md)).
|
||||
23. Garbage collection **MUST** be permitted only on cold paths: the driver, diagnostics, and the
|
||||
CLI. The optimizer, lowering, and backends **MUST NOT** depend on the GC for IR objects.
|
||||
24. The `Context` **MUST** accept an `ArenaAllocator` interface so embedders can supply their own
|
||||
backing memory. The interface **MUST** provide exactly these operations:
|
||||
- `allocate(size, alignment)` returns uninitialized storage owned by the arena; callers MUST
|
||||
NOT assume zeroed storage;
|
||||
- `reset()` returns the arena to its initial state so it can be reused;
|
||||
- `destroy()` releases the arena's backing memory.
|
||||
25. A default bump allocator **MUST** ship in-tree and **MUST** be the allocator used when the
|
||||
embedder supplies none.
|
||||
26. Ownership rules:
|
||||
- Objects allocated into a `Context` or arena live until that arena is reset or destroyed.
|
||||
- A caller **MUST NOT** free an individual arena-owned object. Freeing happens only through
|
||||
`reset` or `destroy`.
|
||||
- A pointer or handle returned across the API **MUST** remain valid until the owning arena is
|
||||
reset or destroyed.
|
||||
- Use of an object after its arena has been reset or destroyed is undefined, and the
|
||||
implementation **MUST NOT** be required to detect it.
|
||||
|
||||
## 10. Configuration
|
||||
|
||||
27. A single `Config` **MUST** carry every setting that affects output. At minimum it **MUST**
|
||||
carry:
|
||||
|
||||
| Field group | Contents |
|
||||
|---|---|
|
||||
| Optimization level | `-O0`, `-O1`, `-O2`, `-O3`, `-Ofast`, `-Oz`. |
|
||||
| Target | `-march`, `-mcpu`, `-target <triple>`. |
|
||||
| Budgets | comptime and HIR budgets (see [004 — HIR Optimizer](004-hir-optimizer.md)) and VIR budgets (see [007 — VIR Optimizer](007-vir-optimizer.md)). |
|
||||
| Pass toggles | enable and disable for every pass exposed as `-f` and `-fno-`. |
|
||||
| Warning policy | `-Wall`, `-Wextra`, `-Werror`, `-Wno-error[=<category>]`, `-w`. |
|
||||
| C compiler selection | `-cc=gcc` or `-cc=clang`, or automatic discovery. |
|
||||
| Mode | `-S`, `-emit-llvm`/`-llvm`, or `-mangled`. |
|
||||
|
||||
28. The CLI **MUST** be a pure function from `argv` to a `Config`. The library **MUST** take a
|
||||
`Config` and **MUST NOT** read process arguments itself.
|
||||
29. Programmatic callers **MUST** be able to bypass the CLI and construct a `Config` directly.
|
||||
30. The determinism guarantee (section 13) is stated relative to a fixed `Config`.
|
||||
|
||||
## 11. Threading
|
||||
|
||||
31. libVCT **MUST** be thread-safe when each compilation unit has its own `Context` and arenas.
|
||||
32. libVCT **MUST NOT** hold shared mutable global state.
|
||||
33. Intra-module parallelism is internal and **MUST** be bounded by the `-j` setting. The
|
||||
observed output **MUST NOT** depend on `-j` (see [000 — Overview](000-overview.md)).
|
||||
|
||||
## 12. Versioning
|
||||
|
||||
34. The library **MUST** follow semantic versioning.
|
||||
35. The textual IR format **MUST** carry its own version, independent of the library version.
|
||||
36. The trait vocabulary **MUST** carry its own version. Adding an attribute or request is a
|
||||
backward-compatible change; changing the meaning of an existing one is a major change.
|
||||
37. Experimental passes **MUST** be gated behind feature flags so that default behavior stays
|
||||
stable within a minor version.
|
||||
|
||||
## 13. Determinism guarantee
|
||||
|
||||
38. For a fixed `Config` and a fixed input, libVCT **MUST** produce byte-identical output on every
|
||||
run, independent of thread count. This binds HIR optimization, lowering, VIR optimization,
|
||||
and both backends. It is a correctness property, not an optimization.
|
||||
39. Determinism **MUST** be demonstrated in CI as specified in [012 — Testing](012-testing.md).
|
||||
|
||||
## 14. Invariants
|
||||
|
||||
- The C API and the D API **MUST** expose the same behavior; a divergence is a bug in the shim.
|
||||
- An arena **MUST** be reclaimable as a unit; no arena-owned object may outlive its arena.
|
||||
- A stage **MUST NOT** depend on shared mutable global state.
|
||||
- The same `Config` and input **MUST** yield the same bytes regardless of `-j`.
|
||||
|
||||
## 15. Cross-references
|
||||
|
||||
- [000 — Overview](000-overview.md) for goals, non-goals, and the determinism guarantee.
|
||||
- [001 — Architecture](001-architecture.md) for the module map and interfaces.
|
||||
- [002 — Traits](002-traits.md) for epochs and the trait vocabulary version.
|
||||
- [004 — HIR Optimizer](004-hir-optimizer.md) for budget names and defaults.
|
||||
- [007 — VIR Optimizer](007-vir-optimizer.md) for VIR budget names and defaults.
|
||||
- [010 — Driver & CLI](010-driver-cli.md) for flag semantics and C compiler discovery.
|
||||
- [012 — Testing](012-testing.md) for determinism tests and the fixture harness.
|
||||
Reference in New Issue
Block a user