feat(ffi-linkage): consume export "csym" rename (Phase 2.2) — 1227 green

The define path now honors the optional `export … "csym"` symbol-name
override (gap iii). declareFunction's rename branch fires for `export` too:
the extern stub is declared under the C name and the sx→C mapping recorded
in foreign_name_map. lazyLowerFunction then resolves the stub by that C
name (via foreign_name_map) so the body promotes into the C-named function
— emitting `define @triple_c` instead of `@sx_triple`. sx-side call sites
to the sx name resolve through the same map (verified: 5*5 prints 25).

example/1227 greens: the companion C calls `triple_c` and prints
call_triple(7) = 22. Bare export (1226) is unaffected (no rename → sx
name). Suite green (638 corpus / 443 unit). Phase 2 (`export`) complete.
This commit is contained in:
agra
2026-06-14 14:53:37 +03:00
parent 66d9169e59
commit 23feea6a0c

View File

@@ -2124,11 +2124,14 @@ pub fn declareFunction(self: *Lowering, fd: *const ast.FnDecl, name: []const u8)
const cc: Function.CallingConvention = if (fd.call_conv == .c or is_foreign or is_extern_decl or fd.extern_export == .export_) .c else .default;
// Symbol-name override: `#foreign … "csym"` (foreign_expr.c_name) or the new
// `extern … "csym"` (fd.extern_name). Declare under the C name and map the sx
// name → C name so call sites resolve to the real symbol.
// `extern … "csym"` / `export … "csym"` (fd.extern_name). Declare under the C
// name and map the sx name → C name so call sites resolve to the real symbol.
// For `export` the stub is later promoted to a real definition (the body
// lowers into this C-named function via lazyLowerFunction — Phase 2.2).
const is_export_decl = fd.extern_export == .export_;
const rename_c_name: ?[]const u8 = if (is_foreign)
fd.body.data.foreign_expr.c_name
else if (is_extern_decl)
else if (is_extern_decl or is_export_decl)
fd.extern_name
else
null;
@@ -2330,7 +2333,13 @@ pub fn lazyLowerFunction(self: *Lowering, name: []const u8) void {
// FIRST author of a name owns this slot. A shadowed same-name author is
// not here (it has no name-keyed slot); it is lowered out-of-line into
// its OWN FuncId by `lowerRetainedSameNameAuthors`.
const name_id = self.module.types.internString(name);
// A renamed `export … "csym"` fn was declared under its C symbol name
// (declareFunction's rename path), so search for the stub under that name
// and promote the body into it. `foreign_name_map` only carries an entry
// when a rename was registered; a bare export / normal define keeps its sx
// name (Phase 2.2).
const search_name = self.foreign_name_map.get(name) orelse name;
const name_id = self.module.types.internString(search_name);
var func_id: ?FuncId = null;
for (self.module.functions.items, 0..) |func, i| {
if (func.name == name_id) {