195 lines
6.8 KiB
Markdown
195 lines
6.8 KiB
Markdown
# Globals and Lifecycle Lowering to IRBackend and IRVM Decision
|
|
|
|
Status: Accepted
|
|
Date: 2026-03-22
|
|
Related Agenda: `docs/compiler/pbs/agendas/19.4. Globals and Lifecycle Lowering to IRBackend/IRVM Agenda.md`
|
|
|
|
## Context
|
|
|
|
After closing globals, lifecycle markers, and published wrapper ownership, PBS v1 still needed a precise lowering contract for how those decisions appear in executable compiler artifacts.
|
|
|
|
The remaining problem was not semantic policy anymore.
|
|
It was structural representation:
|
|
|
|
- where globals become explicit,
|
|
- how synthetic lifecycle callables are represented,
|
|
- how one-shot boot state is materialized,
|
|
- how diagnostics and attribution survive synthetic lowering,
|
|
- and what minimum backend shape must be preserved before `IRVM`.
|
|
|
|
Important fixed inputs already existed:
|
|
|
|
- runtime globals are part of the PBS source model,
|
|
- module init and project init are semantically defined,
|
|
- the published wrapper is the physical entrypoint,
|
|
- `FRAME_RET` belongs to that wrapper,
|
|
- and VM-level global access already exists as `GET_GLOBAL` / `SET_GLOBAL`.
|
|
|
|
## Decision
|
|
|
|
PBS adopts the following lowering policy in v1:
|
|
|
|
1. Globals must become explicit structural entities at the `IRBackend` boundary.
|
|
2. Globals must not be deferred to an implicit late materialization below that boundary.
|
|
3. The lowering pipeline must represent synthetic lifecycle artifacts explicitly as synthetic callables rather than ad hoc emitted fragments.
|
|
4. The following synthetic callable classes are mandatory:
|
|
- `FILE_INIT_FRAGMENT`
|
|
- `MODULE_INIT`
|
|
- `PROJECT_INIT`
|
|
- `PUBLISHED_FRAME_WRAPPER`
|
|
5. The wrapper published as the physical entrypoint must exist explicitly in the lowered graph.
|
|
6. The one-shot boot guard must exist explicitly as a hidden global.
|
|
7. That hidden global is compiler-owned internal state and is not user-visible.
|
|
8. The lowering path must target the already-existing VM global operations:
|
|
- `GET_GLOBAL`
|
|
- `SET_GLOBAL`
|
|
|
|
## IRBackend Shape
|
|
|
|
PBS adopts the following minimum structural shape for `IRBackend`-level representation.
|
|
|
|
### Globals
|
|
|
|
Each backend global must preserve, at minimum:
|
|
|
|
1. `name`
|
|
2. `ownerModuleId`
|
|
3. `type`
|
|
4. `slot`
|
|
5. `visibility`
|
|
6. `isHidden`
|
|
7. `origin`
|
|
|
|
This applies both to:
|
|
|
|
- user-authored globals,
|
|
- and compiler-generated hidden globals such as the boot guard.
|
|
|
|
### Callables
|
|
|
|
The backend must distinguish explicitly between:
|
|
|
|
1. ordinary userland callables,
|
|
2. synthetic compiler-generated callables.
|
|
|
|
Synthetic callables must carry stable class identity rather than being inferred from naming convention alone.
|
|
|
|
### Hidden Global Kind
|
|
|
|
The hidden boot guard must carry explicit structural identity:
|
|
|
|
1. `BOOT_GUARD`
|
|
|
|
It must not be modeled merely as an informal hidden symbol name.
|
|
|
|
## Attribution and Diagnostics
|
|
|
|
PBS adopts the following attribution policy for synthetic lowering:
|
|
|
|
1. Synthetic globals and synthetic callables must carry origin metadata sufficient for remapping errors to real userland code where possible.
|
|
2. Synthetic origin metadata must preserve, at minimum:
|
|
- `derivedFromFile`
|
|
- `derivedFromModule`
|
|
- `derivedFromUserSymbol`
|
|
- `primarySpan`
|
|
- `fallbackSyntheticLabel`
|
|
3. When an error originates from synthetic lowering but has a defensible real userland origin, diagnostics must prefer the real userland span.
|
|
4. Purely synthetic spans should be shown only when no defensible userland origin exists.
|
|
|
|
## Synthetic Callable Policy
|
|
|
|
PBS adopts the following architectural rule:
|
|
|
|
1. Synthetic callables are first-class lowering artifacts.
|
|
2. They are not incidental codegen accidents.
|
|
3. Their explicit class identity exists to support:
|
|
- deterministic ordering,
|
|
- attribution,
|
|
- debug and tooling,
|
|
- conformance tests,
|
|
- and future lifecycle extensions without reopening the lowering model.
|
|
|
|
## Hidden Boot Guard Policy
|
|
|
|
PBS adopts the following policy for the boot guard:
|
|
|
|
1. It exists as a hidden program-owned global.
|
|
2. Userland cannot name it.
|
|
3. Userland cannot read it.
|
|
4. Userland cannot mutate it.
|
|
5. Its sole role is to enforce one-shot bootstrap semantics in the physical wrapper.
|
|
|
|
## Rationale
|
|
|
|
This decision intentionally chooses an explicit backend shape over implicit late-stage magic.
|
|
|
|
That matters because:
|
|
|
|
- globals are now part of the language contract,
|
|
- lifecycle artifacts now exist as semantically meaningful structure,
|
|
- diagnostics must remain attributable to real source even after synthesis,
|
|
- and backend conformance becomes much harder if the representation boundary stays implicit.
|
|
|
|
The chosen model also creates a stable editorial split:
|
|
|
|
- specs explain the structure normatively,
|
|
- and `learn` explains the composition through real source examples.
|
|
|
|
## Structural Diagnostics and Validation
|
|
|
|
PBS must provide, at minimum, the following structural checks or equivalent validation evidence:
|
|
|
|
1. `synthetic wrapper entrypoint missing`
|
|
2. `published entrypoint is not function index 0`
|
|
3. `hidden boot guard is missing`
|
|
4. `synthetic callable origin missing`
|
|
|
|
These may be implemented as backend diagnostics, validation failures, or conformance assertions, as long as the invariant remains enforced and observable.
|
|
|
|
## Invariants
|
|
|
|
1. Globals are explicit at the `IRBackend` boundary.
|
|
2. Synthetic lifecycle callables are explicit at the `IRBackend` boundary.
|
|
3. Hidden compiler state remains distinguishable from user state.
|
|
4. Synthetic lowering must preserve enough origin metadata for defensible remapping.
|
|
5. The lowering path to `IRVM` must preserve the previously accepted wrapper and entrypoint protocol.
|
|
|
|
## Explicit Non-Decisions
|
|
|
|
1. This decision does not redefine source syntax.
|
|
2. This decision does not redefine lifecycle semantics.
|
|
3. This decision does not redefine manifest publication.
|
|
4. This decision does not freeze one concrete implementation class hierarchy.
|
|
|
|
## Spec and Learn Impact
|
|
|
|
This decision should feed at least:
|
|
|
|
1. `docs/compiler/pbs/specs/13. Lowering IRBackend Specification.md`
|
|
2. relevant general lowering specs outside the PBS domain, when they need the new explicit shape
|
|
3. `docs/compiler/pbs/specs/12. Diagnostics Specification.md`
|
|
|
|
It also requires didactic propagation to PBS `learn`, where the model should be explained with source-level examples showing how:
|
|
|
|
1. `declare global`
|
|
2. file `[Init]`
|
|
3. project `[Init]`
|
|
4. and `[Frame]`
|
|
|
|
compose into synthetic lowered artifacts and the published wrapper.
|
|
|
|
## Validation Notes
|
|
|
|
At minimum, validation for this decision should include:
|
|
|
|
1. a fixture combining globals, file init, project init, and frame;
|
|
2. evidence of generated:
|
|
- file init fragment,
|
|
- module init,
|
|
- project init,
|
|
- published wrapper,
|
|
- hidden boot guard;
|
|
3. evidence that the wrapper occupies `func_id = 0`;
|
|
4. evidence that `FRAME_RET` lives in the wrapper path;
|
|
5. evidence that a synthetic-lowering error remaps to real userland span when a defensible origin exists.
|