refactor(ffi-linkage): Phase 7.1 — migrate incidental 12xx ffi examples #foreign→extern
12 plain-C examples that use #foreign incidentally (as FFI plumbing, output unchanged): 1200/1206/1209-1215/1220/1221/1222. Blanket keyword swap; all fn/global markers (no class forms in 12xx). Empty snapshot diff; corpus validates directly (all marker'd). Suite green (647 corpus / 444 unit, 0 failed). KEPT on #foreign (deferred to Phase 8 cutover): identity-#foreign feature tests (filename ffi-foreign-*: 1205/1207/1216/1218/1219), the equivalence test 1228, and the diagnostics that assert on #foreign source/message (1172/1174/1620). Comment-only provenance prose (1223/1229/1230/1231) left intact per Decision-6-recommended.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// `callconv(.c)` on function pointers passed to foreign callbacks — ensures
|
||||
// the function uses C ABI so it can be safely invoked from `#foreign`
|
||||
// the function uses C ABI so it can be safely invoked from `extern`
|
||||
// functions like SDL_AddEventWatch.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 16-byte integer-only struct passed by value through `#foreign`.
|
||||
// 16-byte integer-only struct passed by value through `extern`.
|
||||
//
|
||||
// emit_llvm.zig's `abiCoerceParamType` routes 9..16-byte non-HFA
|
||||
// structs through `[2 x i64]` for register-pair passing on AAPCS64 /
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
Pair64 :: struct { a: i64; b: i64; }
|
||||
|
||||
ffi_pair64_swap :: (p: Pair64) -> Pair64 #foreign;
|
||||
ffi_pair64_swap :: (p: Pair64) -> Pair64 extern;
|
||||
|
||||
main :: () -> i32 {
|
||||
p : Pair64 = .{ a = 1, b = 2 };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Phase 0 baseline (PLAN-FFI.md step 0.1): every primitive type passed
|
||||
// in/out of a C `#foreign` fn via `#import c { #include / #source }`.
|
||||
// in/out of a C `extern` fn via `#import c { #include / #source }`.
|
||||
// Locks today's parameter + return ABI so Phase 1's lowering changes
|
||||
// (`#objc_call` / `#jni_call`) can't silently regress us.
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Phase 0 baseline (PLAN-FFI.md step 0.2): small structs (≤16 bytes)
|
||||
// passed by value into a C `#foreign` fn and returned by value. Four
|
||||
// passed by value into a C `extern` fn and returned by value. Four
|
||||
// shapes that exercise distinct aggregate ABI paths:
|
||||
// Vec2 — 8 B, two f32 (register pair, float)
|
||||
// Vec4f — 16 B, four f32 (HFA — homogeneous float aggregate)
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
// `#source` only — c_import would rewrite struct-typed params/returns
|
||||
// in the .h to *void (its struct/opaque pointer default), losing the
|
||||
// by-value ABI. The hand-written #foreign decls below keep sx's
|
||||
// by-value ABI. The hand-written extern decls below keep sx's
|
||||
// struct types end-to-end.
|
||||
#import c {
|
||||
#source "1210-ffi-02-small-struct.c";
|
||||
@@ -26,21 +26,21 @@ Vec4f :: struct { x: f32; y: f32; z: f32; w: f32; }
|
||||
Pair64 :: struct { a: i64; b: i64; }
|
||||
Quad32 :: struct { a: i32; b: i32; c: i32; d: i32; }
|
||||
|
||||
ffi_vec2_make :: (x: f32, y: f32) -> Vec2 #foreign;
|
||||
ffi_vec2_swap :: (v: Vec2) -> Vec2 #foreign;
|
||||
ffi_vec2_sum :: (v: Vec2) -> f32 #foreign;
|
||||
ffi_vec2_make :: (x: f32, y: f32) -> Vec2 extern;
|
||||
ffi_vec2_swap :: (v: Vec2) -> Vec2 extern;
|
||||
ffi_vec2_sum :: (v: Vec2) -> f32 extern;
|
||||
|
||||
ffi_vec4f_make :: (x: f32, y: f32, z: f32, w: f32) -> Vec4f #foreign;
|
||||
ffi_vec4f_reverse :: (v: Vec4f) -> Vec4f #foreign;
|
||||
ffi_vec4f_sum :: (v: Vec4f) -> f32 #foreign;
|
||||
ffi_vec4f_make :: (x: f32, y: f32, z: f32, w: f32) -> Vec4f extern;
|
||||
ffi_vec4f_reverse :: (v: Vec4f) -> Vec4f extern;
|
||||
ffi_vec4f_sum :: (v: Vec4f) -> f32 extern;
|
||||
|
||||
ffi_pair64_make :: (a: i64, b: i64) -> Pair64 #foreign;
|
||||
ffi_pair64_swap :: (p: Pair64) -> Pair64 #foreign;
|
||||
ffi_pair64_sum :: (p: Pair64) -> i64 #foreign;
|
||||
ffi_pair64_make :: (a: i64, b: i64) -> Pair64 extern;
|
||||
ffi_pair64_swap :: (p: Pair64) -> Pair64 extern;
|
||||
ffi_pair64_sum :: (p: Pair64) -> i64 extern;
|
||||
|
||||
ffi_quad32_make :: (a: i32, b: i32, c: i32, d: i32) -> Quad32 #foreign;
|
||||
ffi_quad32_reverse :: (q: Quad32) -> Quad32 #foreign;
|
||||
ffi_quad32_sum :: (q: Quad32) -> i32 #foreign;
|
||||
ffi_quad32_make :: (a: i32, b: i32, c: i32, d: i32) -> Quad32 extern;
|
||||
ffi_quad32_reverse :: (q: Quad32) -> Quad32 extern;
|
||||
ffi_quad32_sum :: (q: Quad32) -> i32 extern;
|
||||
|
||||
main :: () -> i32 {
|
||||
// ── Vec2 (8 bytes, float pair) ─────────────────────────────────
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Phase 0 baseline (PLAN-FFI.md step 0.3): structs >16 bytes passed
|
||||
// by value into a C `#foreign` fn and returned by value. Exercises
|
||||
// by value into a C `extern` fn and returned by value. Exercises
|
||||
// the byval-pointer ABI path — the caller copies the struct onto its
|
||||
// stack and hands a pointer to the callee; on AAPCS64 the return
|
||||
// uses the indirect `x8` register; on SysV AMD64 the return is a
|
||||
@@ -25,14 +25,14 @@ Big48 :: struct {
|
||||
d: i64; e: i64; f: i64;
|
||||
}
|
||||
|
||||
ffi_big24_make :: (a: i64, b: i64, c: i64) -> Big24 #foreign;
|
||||
ffi_big24_rotate :: (v: Big24) -> Big24 #foreign;
|
||||
ffi_big24_sum :: (v: Big24) -> i64 #foreign;
|
||||
ffi_big24_make :: (a: i64, b: i64, c: i64) -> Big24 extern;
|
||||
ffi_big24_rotate :: (v: Big24) -> Big24 extern;
|
||||
ffi_big24_sum :: (v: Big24) -> i64 extern;
|
||||
|
||||
ffi_big48_make :: (a: i64, b: i64, c: i64,
|
||||
d: i64, e: i64, f: i64) -> Big48 #foreign;
|
||||
ffi_big48_reverse :: (v: Big48) -> Big48 #foreign;
|
||||
ffi_big48_sum :: (v: Big48) -> i64 #foreign;
|
||||
d: i64, e: i64, f: i64) -> Big48 extern;
|
||||
ffi_big48_reverse :: (v: Big48) -> Big48 extern;
|
||||
ffi_big48_sum :: (v: Big48) -> i64 extern;
|
||||
|
||||
main :: () -> i32 {
|
||||
// ── Big24 (24 bytes, byval pointer) ────────────────────────────
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
FQuad :: struct { a: f32; b: f32; c: f32; d: f32; }
|
||||
DQuad :: struct { a: f64; b: f64; c: f64; d: f64; }
|
||||
|
||||
ffi_fquad_make :: (a: f32, b: f32, c: f32, d: f32) -> FQuad #foreign;
|
||||
ffi_fquad_reverse :: (v: FQuad) -> FQuad #foreign;
|
||||
ffi_fquad_sum :: (v: FQuad) -> f32 #foreign;
|
||||
ffi_fquad_make :: (a: f32, b: f32, c: f32, d: f32) -> FQuad extern;
|
||||
ffi_fquad_reverse :: (v: FQuad) -> FQuad extern;
|
||||
ffi_fquad_sum :: (v: FQuad) -> f32 extern;
|
||||
|
||||
ffi_dquad_make :: (a: f64, b: f64, c: f64, d: f64) -> DQuad #foreign;
|
||||
ffi_dquad_reverse :: (v: DQuad) -> DQuad #foreign;
|
||||
ffi_dquad_sum :: (v: DQuad) -> f64 #foreign;
|
||||
ffi_dquad_make :: (a: f64, b: f64, c: f64, d: f64) -> DQuad extern;
|
||||
ffi_dquad_reverse :: (v: DQuad) -> DQuad extern;
|
||||
ffi_dquad_sum :: (v: DQuad) -> f64 extern;
|
||||
|
||||
main :: () -> i32 {
|
||||
// ── FQuad (16 B, 4×f32 HFA) ────────────────────────────────────
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
#source "1213-ffi-05-string-args.c";
|
||||
};
|
||||
|
||||
ffi_strlen :: (s: [:0]u8) -> i32 #foreign;
|
||||
ffi_first_byte :: (s: [:0]u8) -> i32 #foreign;
|
||||
ffi_sum_bytes :: (buf: [*]u8, len: i32) -> i32 #foreign;
|
||||
ffi_write_byte :: (buf: [*]u8, idx: i32, v: u8) -> void #foreign;
|
||||
ffi_static_greeting :: () -> [*]u8 #foreign;
|
||||
ffi_strlen :: (s: [:0]u8) -> i32 extern;
|
||||
ffi_first_byte :: (s: [:0]u8) -> i32 extern;
|
||||
ffi_sum_bytes :: (buf: [*]u8, len: i32) -> i32 extern;
|
||||
ffi_write_byte :: (buf: [*]u8, idx: i32, v: u8) -> void extern;
|
||||
ffi_static_greeting :: () -> [*]u8 extern;
|
||||
|
||||
main :: () -> i32 {
|
||||
// ── [:0]u8 null-terminated literal ─────────────────────────────
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#source "1214-ffi-06-callback.c";
|
||||
};
|
||||
|
||||
ffi_apply_callback :: (cb: (i32) -> i32 callconv(.c), value: i32) -> i32 #foreign;
|
||||
ffi_apply_callback2 :: (cb: (*void, i32) -> i32 callconv(.c), ctx: *void, v: i32) -> i32 #foreign;
|
||||
ffi_apply_callback :: (cb: (i32) -> i32 callconv(.c), value: i32) -> i32 extern;
|
||||
ffi_apply_callback2 :: (cb: (*void, i32) -> i32 callconv(.c), ctx: *void, v: i32) -> i32 extern;
|
||||
|
||||
g_callback_hits : i32 = 0;
|
||||
g_callback_sum : i32 = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// search branch (`<exe>/../../library` etc.), not by the CWD or
|
||||
// importing-file's-dir branches.
|
||||
//
|
||||
// `#include` triggers c_import.zig's auto-synthesis of `#foreign`
|
||||
// `#include` triggers c_import.zig's auto-synthesis of `extern`
|
||||
// fn decls from the C header; `#source` adds the .c to the build's
|
||||
// object list. Together they let the sx side call the C functions
|
||||
// by their declared names with no manual decls.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// `#import c` foreign-name exemption: C names that collide with sx's reserved
|
||||
// type spellings import unedited. Foreign decls are treated as RAW — their names
|
||||
// are never type-classified nor reserved-checked — so the generated `#foreign`
|
||||
// are never type-classified nor reserved-checked — so the generated `extern`
|
||||
// bindings import and call without hand-edits (no backticks needed). This covers
|
||||
// parameter names (`i1`/`i2`), a function whose own NAME is a reserved spelling
|
||||
// (`i2`), and bare-calling that function (its callee spelling parses as a type
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#import "modules/std.sx";
|
||||
|
||||
libc :: #library "c";
|
||||
err_text :: (code: i32) -> [:0]u8 #foreign libc "strerror";
|
||||
sig_text :: (sig: i32) -> ?[:0]u8 #foreign libc "strsignal";
|
||||
dlerror :: () -> ?[:0]u8 #foreign libc;
|
||||
err_text :: (code: i32) -> [:0]u8 extern libc "strerror";
|
||||
sig_text :: (sig: i32) -> ?[:0]u8 extern libc "strsignal";
|
||||
dlerror :: () -> ?[:0]u8 extern libc;
|
||||
|
||||
main :: () -> i32 {
|
||||
// plain: strerror(0) = "Undefined error: 0" on macOS — assert shape,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// The `cstring` type: ONE pointer to a null-terminated u8 buffer — C's
|
||||
// `char *`. Crosses #foreign boundaries verbatim in both directions;
|
||||
// `char *`. Crosses extern boundaries verbatim in both directions;
|
||||
// `?cstring` is the nullable case (null pointer = absent); string
|
||||
// LITERALS coerce implicitly (terminated constants); arbitrary strings
|
||||
// materialize via to_cstring; from_cstring is the zero-copy view back.
|
||||
#import "modules/std.sx";
|
||||
|
||||
libc :: #library "c";
|
||||
strerror_c :: (code: i32) -> cstring #foreign libc "strerror";
|
||||
getenv_c :: (name: cstring) -> ?cstring #foreign libc "getenv";
|
||||
dlerror_c :: () -> ?cstring #foreign libc "dlerror";
|
||||
strerror_c :: (code: i32) -> cstring extern libc "strerror";
|
||||
getenv_c :: (name: cstring) -> ?cstring extern libc "getenv";
|
||||
dlerror_c :: () -> ?cstring extern libc "dlerror";
|
||||
|
||||
main :: () -> i32 {
|
||||
// literal -> cstring param; cstring return -> view
|
||||
|
||||
Reference in New Issue
Block a user