Object Build & Debugging
The object runner exists to answer one question precisely:
Which parts of the compiler can already be lowered to native COFF objects, and where does lowering fail?
For SWC, this question is deliberately narrower than “did the compiler command exit successfully?â€. A source unit may be parsed, indexed, lowered partially, emitted as an object, linked into a PE image, or executed successfully. These are different milestones. Reports must name the highest milestone that was actually observed.
Stable strategy
The reliable build strategy is one Semantic unit per child process.
- several units run in parallel;
- each process has a hard timeout;
- a failed unit does not abort the queue;
- successful units persist their
.objfiles; - status and logs remain available after the run.
SWC evidence levels
| Evidence | What it proves | What it does not prove |
|---|---|---|
| source unit | Semantic source exists in the compiler graph | the unit is linked or executable |
| contract or route | the intended semantic seam is named and validated | machine-code emission is complete |
| COFF object | one unit emitted a persisted native object | all symbols, relocations, or runtime behavior are correct |
| linked PE | objects were combined into a Windows image | the entry point and generated program are runnable |
| runtime executable | the produced image starts and behaves for the tested case | selfhosting or universal UAST coverage |
| Stage 2 → Stage 3 proof | the compiler recompiles its source under the declared deterministic contract | unsupported features may be silently ignored |
A small PE file or a zero exit code is therefore not enough to claim a completed SWC backend. In particular, a fallback return stub must be reported as a stub.
Status phases
| Phase | Meaning |
|---|---|
queued |
waiting for a worker slot |
compiling |
worker process active |
objects_ready |
unit compiled and objects were persisted |
failed |
compiler returned a real diagnostic |
timeout |
worker exceeded the hard timeout and was killed |
Common error families
NATIVE_EXTERNAL_VALUE_UNRESOLVED
Example:
NATIVE_EXTERNAL_VALUE_UNRESOLVED: "m.Rows"
Usually means the source-level selector exists but the native selector cannot map its base value/type/layout safely.
NATIVE_UNRESOLVED_BINDING
Example:
NATIVE_UNRESOLVED_BINDING: "ID"
Often indicates that a transported node retained the field or local name but lost enough context to identify the source binding.
native member ... has no structured layout
The compiler found a member operation but cannot prove a safe field offset for the base type.
UNIMPLEMENTED_NATIVE_GAP
A structural native lowering case is recognized but not yet implemented. This is intentionally explicit.
Debugging by family, not file
A single resolver bug can affect dozens of compiler units. The preferred loop is:
run all units
→ group errors by root cause
→ implement one general fix
→ run all units again
→ compare ready/object counts
This is more valuable than patching individual functions with special cases.
AI-assisted object debugging
This workflow is also the development model for building Semantic with AI for AI. Human developers define the semantic contract and the required proof. AI workers inspect one unit or one error family, follow bindings and relation evidence, propose a general fix, run the focused object probe, and record whether the result reached source, lowering, object, link, runtime, or selfhosting status.
The worker model is intentionally evidence-oriented. Several independent units may be processed in parallel, but their results are not merged into a claim until diagnostics, object files, logs, and exit states have been checked. An AI must not infer that a whole compiler is native merely because many units succeeded.
AI debugging loop
This makes the compiler legible to future AI systems: each failure has a named semantic cause, each fix has a bounded scope, and each claimed capability points to an artifact or test rather than to optimistic prose.
What a useful report contains
- total/ready/failed/timeout counts;
- object count;
- one current error per failed unit;
- worker durations;
- object paths;
- worker logs where needed.
Historical example
An earlier stable report showed 95 total units with 16 ready units and 54 objects. Later resolver work substantially increased object production. Treat these numbers as development snapshots, not compatibility guarantees.
Current SWC boundary
SWC currently exposes native version/help and compile CLI paths, the Semantic reader pipeline, the current canonical UAST subset, transpiler-matrix data, module/lowering contracts, and the PE-target contract. Complete rich-UAST lowering, full machine-code emission, executable link closure, and Windows selfhosting remain in progress. The old Go transpiler is still a behavioral reference for missing capabilities, not proof that those capabilities already exist in SWC.