From 23feea6a0c8f553a2839b70c9a2837931b621cea Mon Sep 17 00:00:00 2001 From: agra Date: Sun, 14 Jun 2026 14:53:37 +0300 Subject: [PATCH] =?UTF-8?q?feat(ffi-linkage):=20consume=20export=20"csym"?= =?UTF-8?q?=20rename=20(Phase=202.2)=20=E2=80=94=201227=20green?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/ir/lower/decl.zig | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/ir/lower/decl.zig b/src/ir/lower/decl.zig index 3e95732..bc963f5 100644 --- a/src/ir/lower/decl.zig +++ b/src/ir/lower/decl.zig @@ -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) {