comptime compiler-API: Phase 1 foundation + Phase 2.1 weld plan
Introduce the welded comptime `compiler` library (`#library "compiler"` +
`abi(.zig) extern compiler`), per design/comptime-compiler-api.md, and unify
`callconv(...)` into the new `abi(...)` annotation.
abi(...) replaces callconv(...):
- New ABI enum { default, c, zig, pure }; `abi(.c|.zig|.pure)` parses in the
postfix slot before extern/export (and standalone). `kw_callconv` -> `kw_abi`.
- Migrated 52 sx files, the call-convention-mismatch diagnostic, and docs
(readme/specs) from `callconv(.c)` to `abi(.c)`.
Phase 1 — welded compiler library (parse -> registry -> validation -> bridge):
- `abi(.zig) extern compiler` parses on fn decls (carries abi/extern_lib) and
struct decls (StructDecl.abi/extern_lib).
- `#library "compiler"` is the comptime-only internal surface — never dlopen'd.
- src/ir/compiler_lib.zig: the binding registry (the safety boundary). `Field`
welded to StructInfo.Field with layout baked from the real Zig type
(@offsetOf/@sizeOf); `findType`/`findFn`. Welded structs are layout-validated
at registration (field set + total size) as a header checked against the impl.
- Host-call bridge: a `fn abi(.zig) extern compiler` dispatches under the
comptime interp to its registered Zig handler (intern/text_of round-trip),
never dlsym. IR Function.compiler_welded; validated in declareFunction.
- Comptime-only enforcement: a runtime call to a welded fn is a clean
build-gating error (emitCall), not an undefined-symbol link failure.
Phase 2.1 — byte-layout weld foundation:
- Decision: full byte-layout weld (sx struct laid out byte-identically to the
bound Zig type). Registered StructInfo (first non-natural / Zig-reordered
layout). `computeWeldPlan` — pure offset-ordered element plan + padding +
sx-field->LLVM-element remap; unit-tested. Emit/interp wiring is the next
sub-step (2.2+, see current/CHECKPOINT-COMPILER-API.md).
Examples: 0625/0626 (welded struct + fn round-trip), 1183/1184/1185
(layout-mismatch, unexported-fn, runtime-call diagnostics).
This commit is contained in:
52
src/ast.zig
52
src/ast.zig
@@ -122,14 +122,26 @@ pub const Root = struct {
|
||||
decls: []const *Node,
|
||||
};
|
||||
|
||||
pub const CallingConvention = enum { default, c };
|
||||
/// ABI / calling-convention annotation written as the postfix `abi(.x)` form on a
|
||||
/// function declaration, function-type literal, or lambda. Subsumes the old
|
||||
/// `callconv(...)` spelling.
|
||||
/// - `.default` — no annotation: the ordinary sx-internal convention (implicit
|
||||
/// context, sx ABI). There is no surface spelling for `.default`; it is the
|
||||
/// value when `abi(...)` is absent.
|
||||
/// - `.c` — C ABI / cdecl, no implicit context (what `callconv(.c)` meant).
|
||||
/// - `.zig` — welded to the real internal Zig type/fn: layout follows the bound
|
||||
/// Zig type, functions dispatch over the comptime host-call bridge. The
|
||||
/// `compiler` library (`design/comptime-compiler-api.md`) binds via `abi(.zig)`.
|
||||
/// - `.pure` — a pure / naked function (inline asm body), no calling-convention
|
||||
/// prologue/epilogue.
|
||||
pub const ABI = enum { default, c, zig, pure };
|
||||
|
||||
/// Linkage modifier written in the postfix slot after `callconv(...)`:
|
||||
/// `name :: (sig) -> Ret [callconv(.x)] [extern | export] [;|{…}];`
|
||||
/// `extern` = import (external linkage, C ABI, no sx ctx — `extern`'s role);
|
||||
/// `export` = define + expose (body + external linkage + C ABI + no ctx).
|
||||
/// Both imply `callconv(.c)`. Variants carry a trailing `_` to dodge the Zig
|
||||
/// keywords. `.none` = no linkage modifier (the ordinary sx-internal decl).
|
||||
/// Linkage modifier written in the postfix slot before `abi(...)`:
|
||||
/// `name :: (sig) -> Ret [extern | export] [abi(.x)] [lib] [;|{…}];`
|
||||
/// `extern` = import (external linkage, no sx ctx — `extern`'s role);
|
||||
/// `export` = define + expose (body + external linkage + no ctx).
|
||||
/// Variants carry a trailing `_` to dodge the Zig keywords. `.none` = no linkage
|
||||
/// modifier (the ordinary sx-internal decl).
|
||||
pub const ExternExportModifier = enum { none, extern_, export_ };
|
||||
|
||||
pub const FnDecl = struct {
|
||||
@@ -139,10 +151,15 @@ pub const FnDecl = struct {
|
||||
body: *Node,
|
||||
type_params: []const StructTypeParam = &.{},
|
||||
is_arrow: bool = false,
|
||||
call_conv: CallingConvention = .default,
|
||||
/// Postfix linkage modifier (`extern`/`export`) written after the
|
||||
/// `callconv(...)` slot. `.none` for an ordinary sx-internal function.
|
||||
/// Parsed in Phase 0.1; not consumed by the fn-decl path until Phase 1.
|
||||
/// ABI / calling-convention annotation (`abi(.c)` / `abi(.zig)` / `abi(.pure)`)
|
||||
/// in the postfix slot after `extern`/`export`. `.default` = unannotated.
|
||||
/// `.zig` marks a function bound to the comptime `compiler` library — its
|
||||
/// signature is welded to the real internal Zig fn and it dispatches over the
|
||||
/// host-call bridge at comptime (consumed by the binding registry + host-call
|
||||
/// bridge in later phases).
|
||||
abi: ABI = .default,
|
||||
/// Postfix linkage modifier (`extern`/`export`) written before the `abi(...)`
|
||||
/// slot. `.none` for an ordinary sx-internal function.
|
||||
extern_export: ExternExportModifier = .none,
|
||||
/// Optional library reference + symbol-name override for an `extern`/`export`
|
||||
/// function, the optional library + symbol-name override. Both
|
||||
@@ -510,6 +527,15 @@ pub const StructDecl = struct {
|
||||
using_entries: []const UsingEntry = &.{},
|
||||
methods: []const *Node = &.{}, // fn_decl nodes for struct methods
|
||||
constants: []const *Node = &.{}, // const_decl nodes for struct-level constants
|
||||
/// ABI / layout annotation (`struct abi(.zig) extern <lib> { … }`). `.default`
|
||||
/// for an ordinary struct. `.zig` marks a layout-welded binding to the named
|
||||
/// `compiler` library's real Zig type — its field offsets are taken from the
|
||||
/// bound Zig type (`@offsetOf`) and asserted equal at compiler-build time.
|
||||
/// Parsed in Phase 1; consumed by the binding registry + layout engine later.
|
||||
abi: ABI = .default,
|
||||
/// The bound library handle for an `abi(.zig) extern <lib>` welded struct
|
||||
/// (e.g. `compiler`); null for an ordinary struct.
|
||||
extern_lib: ?[]const u8 = null,
|
||||
/// True when the declared NAME was a backtick raw identifier
|
||||
/// (`` `i2 :: struct { … } ``) — exempt from the reserved-type-name decl
|
||||
/// check. A bare reserved-name decl still errors.
|
||||
@@ -533,7 +559,7 @@ pub const Lambda = struct {
|
||||
return_type: ?*Node,
|
||||
body: *Node,
|
||||
type_params: []const StructTypeParam = &.{},
|
||||
call_conv: CallingConvention = .default,
|
||||
abi: ABI = .default,
|
||||
};
|
||||
|
||||
pub const TypeExpr = struct {
|
||||
@@ -805,7 +831,7 @@ pub const FunctionTypeExpr = struct {
|
||||
param_types: []const *Node,
|
||||
param_names: ?[]const ?[]const u8 = null, // optional documentation names
|
||||
return_type: ?*Node, // null = void return
|
||||
call_conv: CallingConvention = .default,
|
||||
abi: ABI = .default,
|
||||
};
|
||||
|
||||
pub const ClosureTypeExpr = struct {
|
||||
|
||||
Reference in New Issue
Block a user